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

flow_namespaces() #128

Open
moodymudskipper opened this issue Nov 8, 2022 · 2 comments
Open

flow_namespaces() #128

moodymudskipper opened this issue Nov 8, 2022 · 2 comments
Milestone

Comments

@moodymudskipper
Copy link
Owner

moodymudskipper commented Nov 8, 2022

I'd like to see the dependencies between namespaces.

  • Fetch all namespaces with loadedNamespaces()
  • Figure out their dependencies, use installed.packages()
  • optionally include base packages (the "base" package itself is always excluded since all, or virtually all, packages depend on it)
  • blue if package is attached, yellow otherwise, gray for base packages when applicable
  • full arrow for imports, dashed for suggests, fuller arrow for depends if it's possible, I don't know if we care about LinkingTo ?
@moodymudskipper moodymudskipper added this to the 0.1.2 milestone Nov 23, 2022
@moodymudskipper
Copy link
Owner Author

We can use the promote/demote mechanism here.

We would have the base packages demoted by default, i.e. we don't want to see 15 arrows point to {stats} so we just mention it under the parent package.

Maybe all "no dependency other than base" packages should be demoted by default.

This might be the key to trim some messy trees.

I think the main behavior should be to inspect recursive dependencies (there are already tools but the output doesn't look good AFAICT), if we omit any input we look at the loaded namespaces.

@moodymudskipper
Copy link
Owner Author

moodymudskipper commented Mar 28, 2024

Here's a draft. if pkg is NULL we consider current development project and read the DESCRIPTION to fetch deps.

I think by default we should hide default packages and demote packages that have no dependency (not including hidden packages). I think this would be enough to make any diagram very clear (no pollution by rlang, cli, glue...). tidyr has a lot of recursive deps and even it would look fine I think.

Probably better from left to right, and right to left for reverse deps

flow_view_package_deps <- function(pkg = NULL, which = "strong", reverse = FALSE) {
  db <- readRDS(url("https://cran.r-project.org/web/packages/packages.rds"))
  if (is.null(pkg)) {
    desc <- read.dcf("DESCRIPTION")
    pkg <- desc[, "Package"]
    desc <- desc[, intersect(colnames(db), colnames(desc)), drop = FALSE]
    more_cols <- setdiff(colnames(db), colnames(desc))
    more_cols <- t(setNames(rep_len(NA, length(more_cols)), more_cols))
    desc <- cbind(desc, more_cols)[,colnames(db), drop = FALSE]
    db <- db[db[, "Package"] != pkg,, drop = FALSE]
    db <- rbind(desc, db)
  }

  deps <- function(pkg) {
    deps_list <- tools::package_dependencies(pkg, db, which, FALSE, reverse, FALSE)
    deps_list <- Filter(length, deps_list)
    deps_df_list <- Map(data.frame, from = names(deps_list), to = deps_list)
    do.call(rbind, deps_df_list)
  } 
  #ptype <- data.frame(pkg = character(), dep = character())p
  deps_df <- function(pkgs) {
    if (is.null(pkgs)) return(NULL)
    df <- deps(pkgs)
    rbind(df, deps_df(setdiff(df$to, df$from)))
  }
  data <- deps_df(pkg)
  # FIXME: better hide or demote
  data <- subset(data, !to %in% c("stats", "graphics", "grDevices", "utils", "datasets", "methods"))
  
  code <- paste(sprintf("[%s] -> [%s]", data$from, data$to), collapse = "\n")
  out <- flow:::save_nomnoml(code, NULL)
  flow:::as_flow_diagram(out, data, code)
}

flow_view_package_deps("dplyr")

Created on 2024-03-28 with reprex v2.0.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant