Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update package extension naming docs #4000

Merged
merged 1 commit into from
Sep 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions docs/src/creating-packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ Contour = "d38c429a-6771-53c6-b99e-75d170b6e991"
# name of extension to the left
# extension dependencies required to load the extension to the right
# use a list for multiple extension dependencies
PlottingContourExt = "Contour"
ContourExt = "Contour"

[compat]
Contour = "0.6.2"
Expand All @@ -433,9 +433,9 @@ end
end # module
```

`ext/PlottingContourExt.jl` (can also be in `ext/PlottingContourExt/PlottingContourExt.jl`):
`ext/ContourExt.jl` (can also be in `ext/ContourExt/ContourExt.jl`):
```julia
module PlottingContourExt # Should be same name as the file (just like a normal package)
module ContourExt # Should be same name as the file (just like a normal package)

using Plotting, Contour

Expand All @@ -446,8 +446,8 @@ end
end # module
```

Extensions can have any arbitrary name (here `PlottingContourExt`), but using something similar to the format of
this example that makes the extended functionality and dependency of the extension clear is likely a good idea.
Extensions can have arbitrary names (here `ContourExt`), following the format of this example is likely a good idea for extensions with a single dependency.
In `Pkg` output, extension names are always shown together with their parent package name.

!!! compat
Often you will put the extension dependencies into the `test` target so they are loaded when running e.g. `Pkg.test()`. On earlier Julia versions
Expand All @@ -461,8 +461,8 @@ this example that makes the extended functionality and dependency of the extensi

### Behavior of extensions

A user that depends only on `Plotting` will not pay the cost of the "extension" inside the `PlottingContourExt` module.
It is only when the `Contour` package actually gets loaded that the `PlottingContourExt` extension is loaded too
A user that depends only on `Plotting` will not pay the cost of the "extension" inside the `ContourExt` module.
It is only when the `Contour` package actually gets loaded that the `ContourExt` extension is loaded too
and provides the new functionality.

In our example, the new functionality is an additional _method_, which we add to an existing _function_ from the parent package `Plotting`.
Expand All @@ -474,17 +474,17 @@ function plot end
```

!!! note
If one considers `PlottingContourExt` as a completely separate package, it could be argued that defining `Plotting.plot(c::Contour.ContourCollection)` is
[type piracy](https://docs.julialang.org/en/v1/manual/style-guide/#Avoid-type-piracy) since `PlottingContourExt` _owns_ neither the function `Plotting.plot` nor the type `Contour.ContourCollection`.
If one considers `ContourExt` as a completely separate package, it could be argued that defining `Plotting.plot(c::Contour.ContourCollection)` is
[type piracy](https://docs.julialang.org/en/v1/manual/style-guide/#Avoid-type-piracy) since `ContourExt` _owns_ neither the function `Plotting.plot` nor the type `Contour.ContourCollection`.
However, for extensions, it is ok to assume that the extension owns the functions in its parent package.

In other situations, one may need to define new symbols in the extension (types, structs, functions, etc.) instead of reusing those from the parent package.
Such symbols are created in a separate module corresponding to the extension, namely `PlottingContourExt`, and thus not in `Plotting` itself.
Such symbols are created in a separate module corresponding to the extension, namely `ContourExt`, and thus not in `Plotting` itself.
If extension symbols are needed in the parent package, one must call `Base.get_extension` to retrieve them.
Here is an example showing how a custom type defined in `PlottingContourExt` can be accessed in `Plotting`:
Here is an example showing how a custom type defined in `ContourExt` can be accessed in `Plotting`:

```julia
ext = Base.get_extension(@__MODULE__, :PlottingContourExt)
ext = Base.get_extension(@__MODULE__, :ContourExt)
if !isnothing(ext)
ContourPlotType = ext.ContourPlotType
end
Expand Down Expand Up @@ -512,7 +512,7 @@ This is done by making the following changes (using the example above):

@static if !isdefined(Base, :get_extension)
function __init__()
@require Contour = "d38c429a-6771-53c6-b99e-75d170b6e991" include("../ext/PlottingContourExt.jl")
@require Contour = "d38c429a-6771-53c6-b99e-75d170b6e991" include("../ext/ContourExt.jl")
end
end
```
Expand All @@ -526,11 +526,11 @@ This is done by making the following changes (using the example above):
# Other init functionality here

@static if !isdefined(Base, :get_extension)
@require Contour = "d38c429a-6771-53c6-b99e-75d170b6e991" include("../ext/PlottingContourExt.jl")
@require Contour = "d38c429a-6771-53c6-b99e-75d170b6e991" include("../ext/ContourExt.jl")
end
end
```
- Make the following change in the conditionally-loaded code:
- Make the following change in the conditionally-loaded code in `ContourExt.jl`:
```julia
isdefined(Base, :get_extension) ? (using Contour) : (using ..Contour)
```
Expand All @@ -549,7 +549,7 @@ This is done by making the following changes (using the example above):
- Add the following to your main package file (typically at the bottom):
```julia
if !isdefined(Base, :get_extension)
include("../ext/PlottingContourExt.jl")
include("../ext/ContourExt.jl")
end
```

Expand Down
Loading