Modules and Submodules for a Better User Experience

Better User Experience with Submodules

Experience and Found Issues

I have been experimenting with multiple modules/submodules in my latest package, and I am finding it to be maybe a little clunky but I think overall the experience feels better. However, I find the LSP and even the REPL functionality is limited.

For Instance, If I find myself inside a submodule:

module ModA # ModA is the main package

foo() = 1

  module ModA_1
    import ModA
    ModA.foo(x::Int) = 6
  
  end

end

Issue #1

When I do import ModA, I will not get lsp help when doing ModA. (this is in vscode. I tried zed and surprisingly zed does much better with this).

Issue #2

The other piece is when I extend a function like in ModA_1, I will not see that function in the REPL when hitting tab. I get the following:

julia> ModA.ModA_1.

eval
include
julia> ModA.ModA_1.

Brief Look at AISCSteel (not registered yet)

Here is a brief look at my package when organized with submodules:

julia> using AISCSteel
Precompiling AISCSteel
  1 dependency successfully precompiled in 3 seconds. 51 already precompiled.

julia> AISCSteel.
ChapterFFlexure  Classifications
Shapes           Units
Utils            datadir
eval             include
projectdir

julia> AISCSteel.Shapes.
AbstractSteelShapes
CShapes
IShapes
eval
include

julia> AISCSteel.Shapes.IShapes.
AbstractBuiltUpIShapes  AbstractIShapes
AbstractRolledIShapes   BuiltUpIShapes
RolledIShapes           eval
include

julia> AISCSteel.Shapes.IShapes.RolledIShapes.
Flexure  HPShape
MShape   SShape
WShape   eval
include

julia> w = AISCSteel.Shapes.IShapes.RolledIShapes.WShape("w10x12")
AISCSteel.Shapes.IShapes.RolledIShapes.WShape("W10X12", 12.0 plf, 3.54 inch^2, 9.87 inch, 3.96 inch, 0.19 inch, 0.21 inch, 0.51 inch, 0.5625 inch, 8.854 inch, 53.8 inch^4, 12.6 inch^3, 10.9 inch^3, 3.9 inch, 2.18 inch^4, 1.74 inch^3, 1.1 inch^3, 0.785 inch, 0.0547 inch^4, 50.9 inch^6, 9.56 inch^2, 1.99 inch^4, 1.91 inch^3, 6.14 inch^3, 0.983 inch, 9.66 inch, 30.7 inch, 34.7 inch, 23.7 inch, 27.7 inch, 8.375 inch, 2.25 inch, 0.0 inch, 29000.0 ksi, 60.0 ksi)

julia> AISCSteel.Shapes.IShapes.RolledIShapes.Flexure.

F2                F3
F4                F5
calc_Mn           classify_flange
classify_section  classify_web
eval              include

julia> AISCSteel.Shapes.IShapes.RolledIShapes.Flexure.calc_Mn()
calc_Mn(w::T, L_b, C_b) where T<:AbstractRolledIShapes @ AISCSteel.Shapes.IShapes.RolledIShapes.Flexure ~/.julia/dev/AISCSteel/src/Shapes/IShapes/RolledIShapes/Flexure/Flexure.jl:57
calc_Mn(w::T, L_b) where T<:AbstractRolledIShapes @ AISCSteel.Shapes.IShapes.RolledIShapes.Flexure ~/.julia/dev/AISCSteel/src/Shapes/IShapes/RolledIShapes/Flexure/Flexure.jl:57
julia> Mn = AISCSteel.Shapes.IShapes.RolledIShapes.Flexure.calc_Mn(w, 2ft)
61.04138339252868 ft kip

General Julian Way

I know the julian way is to generally not use any sub modules, but I have found this to be difficult when using other packages. I find I usually have to have the docs open at all times. Here is Plots.jl for instance:

julia> Plots.

@P_str                           @add_attributes                  @animate                         @apng                            @attributes
@colorant_str                    @deps                            @ext_imp_use                     @gif                             @init_backend
@layout                          @recipe                          @require_backend                 @series                          @shorthands
@userplot                        ABGR                             ADIN99                           ADIN99d                          ADIN99o
AGray                            AGray32                          AHSI                             AHSL                             AHSV
AKW                              ALCHab                           ALCHuv                           ALMS                             ALab
ALuv                             AMat                             AOklab                           AOklch                           ARGB
ARGB32                           AStr                             AVec                             AXYZ                             AYCbCr
AYIQ                             AbstractAGray                    AbstractARGB                     AbstractBackend                  AbstractGray
AbstractGrayA                    AbstractLayout                   AbstractPlot                     AbstractRGB                      AbstractRGBA
AlphaColor                       AnimatedGif                      Animation                        AreaPlot                         Arrow
Axis                             AxyY                             BGR                              BGRA                             BezierCurve
Brush                            CIE1931JV_CMF                    CIE1931J_CMF                     CIE1931_CMF                      CIE1964_CMF
CIE2006_10_CMF                   CIE2006_2_CMF                    CURRENT_BACKEND                  CURRENT_PLOT                     Color
Color3                           ColorAlpha                       ColorGradient                    ColorPalette                     ColorType
ColorTypes                       Colorant                         ColorantNormed                   ColorbarStyle                    Colors
CurrentBackend                   CurrentPlot                      DEFAULT_BBOX                     DEFAULT_LINEWIDTH                DEFAULT_MINOR_INTERVALS
DEFAULT_MINPAD                   DE_2000                          DE_94                            DE_AB                            DE_BFD
DE_CMC                           DE_DIN99                         DE_DIN99d                        DE_DIN99o                        DE_JPC79
DIN99                            DIN99A                           DIN99d                           DIN99dA                          DIN99o
DIN99oA                          DPI                              EachAnn                          EmptyLayout                      Extrema
Font                             Formatted                        Fractional                       FrameIterator                    GR
GRBackend                        GRColorbar                       GRViewport                       GastonBackend                    Gray
Gray24                           GrayA                            GridLayout                       HDF5Backend                      HDF5PLOT_MAP_STR2TELEM
HDF5PLOT_MAP_TELEM2STR           HDF5PLOT_PLOTREF                 HDF5Plot_PlotRef                 HSB                              HSI
HSIA                             HSL                              HSLA                             HSV                              HSVA
InputWrapper                     InspectDRBackend                 KW                               LCHab                            LCHabA
LCHuv                            LCHuvA                           LMS                              LMSA                             Lab
LabA                             Legend                           Luv                              LuvA                             MM_PER_INCH
MM_PER_PX                        MSC                              Measurement                      NaNSegmentsIterator              NoBackend
OHLC                             Oklab                            OklabA                           Oklch                            OklchA
P"                               P2                               P3                               PGFPlotsBackend                  PGFPlotsXBackend
PLOTS_DEFAULT_BACKEND            PLOTS_SEED                       POTENTIAL_VECTOR_ARGUMENTS       PX_PER_INCH                      PlaceHolder
Plot                             PlotExample                      PlotMeasures                     PlotOrSubplot                    PlotText
PlotTheme                        PlotThemes                       PlotUtils                        PlotlyBackend                    PlotlyJSBackend
PlotsDisplay                     PortfolioComposition             PyPlotBackend                    PythonPlotBackend                RGB
RGB24                            RGBA                             RGBX                             RecipeData                       RecipesBase
RootLayout                       Segments                         Series                           SeriesAnnotations                SeriesSegment
Shape                            ShowTheme                        Spy                              Stroke                           Subplot
SubplotMap                       Surface                          SurfaceFunction                  TicksArgs                        TicksType
Transparent3                     TransparentColor                 TransparentGray                  TransparentRGB                   UnicodePlotsBackend
XRGB                             XYZ                              XYZA                             YCbCr                            YCbCrA
YIQ                              YIQA                             _3dTypes                         ___straightline_data             __heatmap_edges
__init__                         __straightline_data              _add_errorbar_kw                 _add_markershape                 _add_plot_title!
_add_smooth_kw                   _add_the_series                  _add_triangle!                   _allAxes                         _allFramestyles
_allGridArgs                     _allGridSyms                     _allMarkers                      _allScales                       _allShowaxisArgs
_allShowaxisSyms                 _allStyles                       _allTypes                        _all_args                        _all_axis_args
_all_defaults                    _all_magic_args                  _all_plot_args                   _all_series_args                 _all_subplot_args
_already_warned                  _animate                         _animation_examples              _annotation                      _annotation_coords
_annotationfont                  _arg_desc                        _argument_description            _as_gradient                     _attribute_defaults
_attrsymbolcache                 _auto_binning_nbins              _axesAliases                     _axis_args                       _axis_defaults
_axis_defaults_byletter          _backendSymbol                   _backendType                     _backend_instance                _backend_packages
_backend_skips                   _backends                        _bar_width                       _base_supported_args             _before_layout_calcs
_best_html_output_type           _bin_centers                     _binbarlike_baseline             _cbar_unique                     _cbar_width
_check_compat                    _check_installed                 _color_functions                 _create_backend_figure           _current_plots_version
_cycle                           _debug                           _deprecated_attributes           _deprecated_backends             _display
_do_plot_show                    _document_argument               _examples                        _expand_subplot_extrema          _extension_map
_filternans                      _fmt_paragraph                   _framestyleAliases               _gaston_attr                     _gaston_marker
_gaston_scale                    _gaston_seriestype               _gaston_style                    _generate_doclist                _get_showtheme_args
_gr_attr                         _gr_marker                       _gr_scale                        _gr_seriestype                   _gr_style
_guess_best_legend_position      _haligns                         _has_ticks                       _hdf5_attr                       _hdf5_marker
_hdf5_scale                      _hdf5_seriestype                 _hdf5_style                      _heatmap_edges                   _hist_edge
_hist_edges                      _hist_norm_mode                  _histogram_like                  _initial_ax_fontsizes            _initial_axis_defaults
_initial_defaults                _initial_fontsizes               _initial_plt_fontsizes           _initial_sp_fontsizes            _initialize_backend
_initialize_subplot              _initialized_backends            _inspectdr_attr                  _inspectdr_marker                _inspectdr_scale
_inspectdr_seriestype            _inspectdr_style                 _internal_args                   _is_positive                     _keyAliases
_label_func                      _label_func_tex                  _lettered_all_axis_args          _line_like                       _logScaleBases
_logScales                       _magic_axis_args                 _magic_series_args               _magic_subplot_args              _make_hist
_markerAliases                   _match_map                       _match_map2                      _override_seriestype_check       _path
_pgfplots_attr                   _pgfplots_marker                 _pgfplots_scale                  _pgfplots_seriestype             _pgfplots_style
_pgfplotsx_attr                  _pgfplotsx_marker                _pgfplotsx_scale                 _pgfplotsx_series_ids            _pgfplotsx_seriestype
_pgfplotsx_style                 _plot!                           _plot_args                       _plot_defaults                   _plot_setup
_plotly_attr                     _plotly_data_url                 _plotly_data_url_cached          _plotly_local_file_path          _plotly_marker
_plotly_min_js_filename          _plotly_scale                    _plotly_seriestype               _plotly_style                    _plotlyjs_attr
_plotlyjs_marker                 _plotlyjs_scale                  _plotlyjs_seriestype             _plotlyjs_style                  _plots_compats
_plots_defaults                  _plots_deps                      _plots_plotly_defaults           _plots_theme_defaults            _positionAliases
_positive_else_nan               _post_imports                    _pre_imports                     _prepare_subplot                 _preprocess_barlike
_preprocess_binbarlike_weights   _preprocess_binlike              _preprocess_userrecipe           _process_annotation              _process_annotation_2d
_process_annotation_3d           _pyplot_attr                     _pyplot_marker                   _pyplot_scale                    _pyplot_seriestype
_pyplot_style                    _pythonplot_attr                 _pythonplot_marker               _pythonplot_scale                _pythonplot_seriestype
_pythonplot_style                _relative_position               _replace_linewidth               _replace_markershape             _runtime_init
_savemap                         _scaleAliases                    _scale_adjusted_values           _scale_lims                      _segmenting_array_attributes
_segmenting_vector_attributes    _series_added                    _series_args                     _series_defaults                 _series_index
_series_recipe_deps              _series_updated                  _shape_data!                     _shape_keys                      _shapes
_show                            _showjuno                        _slice_series_args!              _splitdef!                       _stepbins_path
_straightline_data               _styleAliases                    _subplot_args                    _subplot_defaults                _subplot_setup
_suppress_warnings               _surface_like                    _text_label                      _theme                           _to_warn
_transform_ticks                 _typeAliases                     _unicodeplots_attr               _unicodeplots_marker             _unicodeplots_scale
_unicodeplots_seriestype         _unicodeplots_style              _update_axis                     _update_axis_colors              _update_axis_links
_update_clims                    _update_inset_padding!           _update_margins                  _update_min_padding!             _update_plot_args
_update_plot_object              _update_series_attributes!       _update_subplot_args             _update_subplot_colorbars        _update_subplot_colors
_update_subplot_periphery        _use_local_dependencies          _use_local_plotlyjs              _valigns                         _widen_seriestypes
_z_colored_series                abline!                          adapted_grid                     addExtension                     add_aliases
add_arrows                       add_axes_aliases                 add_major_or_minor_segments_2d   add_major_or_minor_segments_3d   add_non_underscore_aliases!
add_theme                        aliases                          aliasesAndAutopick               alignment                        allAlphas
allFunctions                     allLineTypes                     allReals                         allShapes                        allStyles
all_seriestypes                  allnan                           alpha                            alphacolor                       animate
annotate!                        annotations                      anynan                           apng                             apngfn
areaplot                         areaplot!                        arrow                            assign_annotation_coord!         attr
attr!                            attributes                       attrtypes                        autopick_ignore_none_auto        axes_letters
axis_drawing_info                axis_drawing_info_3d             axis_limits                      backend                          backend_name
backend_object                   backend_package_name             backends                         bar                              bar!
barh                             barh!                            barhist                          barhist!                         base_color_type
base_colorant_type               bbox                             bbox!                            bbox_to_pcts                     bezier_value
blue                             bool_env                         bottom                           bottompad                        boxplot
boxplot!                         brush                            build_layout                     buildanimation                   calc_num_subplots
cbar_fill                        cbar_gradient                    cbar_lines                       ccolor                           ceil_base
center                           cgrad                            check_aspect_ratio               check_contour_levels             chroma
cie_color_match                  clamp_greys!                     clamp_to_eps!                    closeall                         color
color_list                       color_or_nothing!                color_type                       coloralpha                       colorant"
colorbar_style                   colorbartitlefont                colordiff                        colormap                         colormatch
comp1                            comp2                            comp3                            comp4                            comp5
compute_angle                    compute_gridsize                 compute_minpad                   concatenate_fillrange            contour
contour!                         contour3d                        contour3d!                       contour_levels                   contourf
contourf!                        convertLegendValue               convert_sci_unicode              convert_to_polar                 coords
copy_series!                     current                          curve_points                     curves                           curves!
cvec                             d_point                          debug!                           debugshow                        default
defaultOutputFormat              default_cgrad                    default_widen_factor             density                          density!
deuteranopic                     diagnostics                      discrete_value!                  distinguishable_colors           diverging_palette
dumpdict                         embeddable_html                  ensure_gradient!                 eps                              error_coords
error_style!                     error_tuple                      error_zipit                      eval                             examples
expand_extrema!                  extend_by_data!                  extend_series!                   extend_series_data!              extend_to_length!
extrema_plus_buffer              fakedata                         ffmpeg_framerate                 fg_color                         file_extension
findnz                           float_extended_type              floor_base                       font                             frame
from_polar                       gamutmax                         gamutmin                         gaston                           get_aspect_ratio
get_attr_symbol                  get_axis                         get_clims                        get_color_palette                get_colorbar_ticks
get_colorgradient                get_fillalpha                    get_fillcolor                    get_fillstyle                    get_gradient
get_labels                       get_linealpha                    get_linecolor                    get_linestyle                    get_linewidth
get_markeralpha                  get_markercolor                  get_markerstrokealpha            get_markerstrokecolor            get_markerstrokewidth
get_minor_ticks                  get_series_color                 get_size                         get_sp_lims                      get_subplot
get_subplot_index                get_thickness_scaling            get_ticks                        get_xs                           get_xy
get_ys                           get_z_normalized                 getattr                          getplot                          gif
giffn                            gr                               gr_add_legend                    gr_add_series                    gr_add_title
gr_arrowstyles                   gr_axis_height                   gr_axis_width                    gr_cbar_offsets                  gr_cbar_width
gr_clims                         gr_color                         gr_colorbar_colors               gr_colorbar_info                 gr_colorbar_tick_size
gr_colorbar_title                gr_contour_levels                gr_display                       gr_draw_axes                     gr_draw_axis
gr_draw_axis_3d                  gr_draw_axis_grid                gr_draw_axis_grid_3d             gr_draw_axis_minorgrid           gr_draw_axis_minorgrid_3d
gr_draw_border                   gr_draw_colorbar                 gr_draw_contour                  gr_draw_grid                     gr_draw_heatmap
gr_draw_image                    gr_draw_marker                   gr_draw_markers                  gr_draw_minorgrid                gr_draw_segments
gr_draw_shapes                   gr_draw_spine                    gr_draw_surface                  gr_draw_ticks                    gr_fill_plotarea
gr_fill_styles                   gr_fill_viewport                 gr_font_family                   gr_get_3d_axis_angle             gr_get_legend_geometry
gr_get_ticks_size                gr_getcolorind                   gr_haligns                       gr_inqtext                       gr_is3d
gr_label_axis                    gr_label_axis_3d                 gr_label_ticks                   gr_label_ticks_3d                gr_legend_bbox
gr_legend_marker_to_line_factor  gr_legend_pos                    gr_linetypes                     gr_lw_clamp_factor               gr_markertypes
gr_nominal_size                  gr_point_mult                    gr_polaraxes                     gr_polyline                      gr_polyline3d
gr_projections                   gr_set_arrowstyle                gr_set_bordercolor               gr_set_fill                      gr_set_fillcolor
gr_set_fillstyle                 gr_set_font                      gr_set_gradient                  gr_set_line                      gr_set_linecolor
gr_set_markercolor               gr_set_projectiontype            gr_set_textcolor                 gr_set_tickfont                  gr_set_transparency
gr_set_viewport_cmap             gr_set_viewport_polar            gr_set_window                    gr_text                          gr_text_size
gr_update_colorbar!              gr_update_viewport_legend!       gr_update_viewport_ratio!        gr_valigns                       gr_viewport_bbox
gr_viewport_from_bbox            gr_w3tondc                       gr_x_axislims                    gr_x_log_scales                  gr_xy_axislims
gr_y_axislims                    gr_y_log_scales                  gr_z_axislims                    gr_z_log_scales                  gr_z_normalized_log_scaled
gray                             green                            grid                             grid_factor_2d                   grid_factor_3d
gui                              guide_padding                    guidefont                        handleColors!                    handle_surface
has_attribute_segments           has_black_border_for_default     has_ticks                        hasattr                          hascolorbar
hasgrid                          hdf5                             heatmap                          heatmap!                         heatmap_edges
hex                              hexbin                           hexbin!                          histogram                        histogram!
histogram2d                      histogram2d!                     hline                            hline!                           hspan
hspan!                           html                             html_to_png                      hue                              ignorenan_extrema
ignorenan_maximum                ignorenan_mean                   ignorenan_min_max                ignorenan_minimum                imports
inch2mm                          inch2px                          include                          initialized                      inline
inspectdr                        intersection_point               invisible                        is_2tuple                        is_3d
is_attr_supported                is_axis_attr                     is_axis_attr_noletter            is_horizontal                    is_marker_supported
is_scale_supported               is_series_attr                   is_seriestype_supported          is_style_supported               is_subplot_attr
is_uniformly_spaced              isatom                           isautop                          iscontour                        isdark
isfilledcontour                  isijulia                         ismatrix                         isortho                          ispersp
isplotnull                       ispolar                          ispositive                       isscalar                         istuple
isvector                         isvertical                       iter_segments                    json                             label_to_string
labelfunc                        labelfunc_tex                    layout_args                      lazyloadPkg                      left
leftpad                          legend_anchor_index              legend_angle                     legend_pos_from_angle            legendfont
legendtitlefont                  lens!                            like_histogram                   like_line                        like_surface
limsType                         link_axes!                       link_subplots                    load_default_backend             locate_annotation
lookup_aliases                   make_fillrange_from_ribbon       make_fillrange_side              make_measure_hor                 make_measure_vert
make_non_underscore              make_steps                       makearrowhead                    makecross                        makekw
makeplural                       makeshape                        makestar                         maketuple                        makevec
mapc                             mapreducec                       mean_hue                         merge_with_base_supported        mesh3d
mesh3d!                          mesh3d_triangles                 mirrored                         mm2inch                          mm2px
mov                              movfn                            mp4                              mp4fn                            n
nanappend!                       nanpush!                         nansplit                         nanvcat                          needs_any_3d_axes
no_minor_intervals               normalize_hue                    num_minor_intervals              ohlc                             ohlc!
ok                               open_browser_window              optimal_ticks_and_labels         optimize_datetime_ticks          optimize_ticks
origin                           paddings                         palette                          parametric_colorant              parent_bbox
parse_axis_kw                    partialcircle                    path3d                           path3d!                          pdf
pgfplots                         pgfplotsx                        pgfx_sanitize_string             pie                              pie!
plot                             plot!                            plot3d                           plot3d!                          plot_color
plotarea                         plotarea!                        plotattr                         plotly                           plotlyjs
plots_heatmap                    plots_heatmap!                   plottitlefont                    png                              portfoliocomposition
portfoliocomposition!            position                         position_multiplier              prepare_output                   preprocess_attributes!
processFillArg                   processFontArg!                  processGridArg!                  processLineArg                   processMarkerArg
processMinorGridArg!             process_annotation               process_axis_arg!                process_clims                    process_limits
protanopic                       protectedstring                  ps                               px2inch                          px2mm
pyplot                           pythonplot                       quiver                           quiver!                          quiver_using_arrows
quiver_using_hack                recompute_lengths                recursive_merge                  red                              reducec
remap                            replaceAlias!                    replaceAliases!                  replace_image_with_heatmap       replace_rand
reset_axis_defaults_byletter!    reset_defaults                   reset_extrema!                   resetfontsizes                   
# Had to cut this short because of character limit
julia> Plots.

I have found almost every package to be written this way, and I guess I wanted to see people’s opinions.

  • What do people suggest as the best way to organize code in Julia?
  • Do you see the brief demo of AISCSteel to be more readable?
  • Do you see anyone really working to fix bugs in LSP/REPL code that is organized like mine?
7 Likes

This is as expected, as you say the function is just extended in ModA_1, there’s no foo in ModA_1.

My current style is like this:

  • Try with only a single big file. If more files are warranted, OK, but long-term each file should probably be it’s own package. If there are any additional files, they should only ever be include-d into the top-level module directly (not into submodules).
  • The top level module only contains other modules and a few export-ed const aliases to values defined in the submodules.

What bugs?

Thanks for the response!

Okay I see that. I guess I will just create a new function with the same name in those cases. They can be separate in my use cases so far.

It has to do with Issue #1. If I am inside a submodule (like ModA_1 above), I can not get any help from LSP when importing from the main package (like import ModA). The LSP in vscode will not recognize the main module that I am within. This sort of encourages me not to organize my code.

I have tried this and frankly you end up with 300+ names in the top level and it just isn’t very nice as a user. I know you said to then split it up into individual packages, but then I would need like 100 packages and that is too much. All the separate versioning and compats seems like way too much maintenance for me.

And even if I did get that working, I still think you end up with something that isn’t like I show in the demo above. You would have to know all the 100 packages instead of the 1 package that then guides you where you want to go.

3 Likes

Here’s an example of what I meant, there’s not that many names in the top-level module:

So it looks like this:

module MyPackage
    module Submodule0
        # ...
    end

    module Submodule1
        using ..Submodule0
        # ...
    end

    module Submodule2
        using ..Submodule0, ..Submodule1
        # ...
    end

    export exported_name

    """
        exported_name

    Lorem ipsum dolor sit amet.
    """
    const exported_name = Submodule2.some_name
end

Furthermore, with this structure there’s no need to import the package from its submodules, avoiding the language server bug you describe.

Would it be conceivable to overload getproperty to display what you want at every level instead of creating multiple modules?

I don’t think I plan on exporting any names. The method you show above is essentially the same as what I am doing. using ..Submodule0 and import MyPackage.Submodule0 as Submodule0 and also just import MyPackage will still not give me any lsp help when I do Submodule0. in vscode. Although, it seems to mostly work in zed. I just can’t use that on my windows computer.

Actually after trying this again in vscode. It starts to work with import method after the second . so AISCSteel. gives me nothing but AISCSteel.Shapes. does give me LSP help. This is ok for now!

1 Like

First, thanks for the response!

I don’t see how I could do anything like I show in the demo above with my package. What getproperty would I override for doing AISCSteel.Shapes? I can override AISCSteel but then there would not be a Shapes module to override.

Sorry, I was just speculating, and thought that maybe the idea could be interesting. Maybe currently that’s not possible because a module does not have its own type (it is just a Module), thus we cannot overload getproperty for a specific module.

Second, I’m not sure if it would be conceivable to do that from within the module.

Anyway, it would be nice to be able to overload the behavior of getproperty of the properties of a module to imitate that behavior without imposing a code structure (that would, additionally, allow one to isolate better public vs. private fields of the module).