├── .github ├── .gitignore ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ ├── render-rmarkdown.yaml │ ├── test-coverage.yaml │ └── rhub.yaml ├── .gitattributes ├── tests ├── testthat.R ├── spelling.R ├── testthat │ ├── setup-deepdep.R │ ├── setup-vcr.R │ ├── test-get_available_packages.R │ ├── test-deepdep_declutter.R │ ├── test-development.R │ ├── test-plot_downloads.R │ ├── test-match_dependency_type.R │ └── test-deepdep.R └── fixtures │ ├── deepdep-2.yml │ ├── plot-dd-rlang.yml │ └── plot-dnl-1.yml ├── docs ├── images │ ├── logo.png │ ├── cheatsheet.pdf │ └── cheatsheet.pptx ├── reference │ ├── deepdep-1.png │ ├── deepdep-2.png │ ├── plot_deepdep-1.png │ ├── plot_deepdep-2.png │ ├── plot_deepdep-3.png │ ├── plot_deepdep-4.png │ ├── plot_downloads-1.png │ ├── plot_downloads-2.png │ ├── deepdep_shiny.html │ ├── get_downloads.html │ ├── print.deepdep.html │ ├── print.package_downloads.html │ ├── print.available_packages.html │ └── print.package_dependencies.html ├── README_files │ └── figure-gfm │ │ ├── unnamed-chunk-2-1.png │ │ ├── unnamed-chunk-2-2.png │ │ ├── unnamed-chunk-3-1.png │ │ ├── unnamed-chunk-4-1.png │ │ ├── unnamed-chunk-4-2.png │ │ └── unnamed-chunk-5-1.png ├── articles │ ├── deepdep-comparison_files │ │ ├── figure-html │ │ │ └── miniCRAN-1.png │ │ └── header-attrs-2.1.1 │ │ │ └── header-attrs.js │ ├── deepdep-package_files │ │ ├── figure-html │ │ │ ├── plot_dependencies1-1.png │ │ │ ├── plot_dependencies1-2.png │ │ │ ├── plot_dependencies2-1.png │ │ │ ├── plot_dependencies3-1.png │ │ │ ├── plot_dependencies4-1.png │ │ │ └── plot_dependencies5-1.png │ │ └── header-attrs-2.1.1 │ │ │ └── header-attrs.js │ └── index.html ├── pkgdown.yml ├── link.svg ├── bootstrap-toc.css ├── docsearch.js ├── pkgdown.js ├── bootstrap-toc.js ├── 404.html ├── authors.html ├── news │ └── index.html └── pkgdown.css ├── man ├── figures │ └── logo.png ├── deepdep_shiny.Rd ├── print.deepdep.Rd ├── print.package_downloads.Rd ├── print.available_packages.Rd ├── print.package_dependencies.Rd ├── print.package_description.Rd ├── get_downloads.Rd ├── get_description.Rd ├── get_available_packages.Rd ├── plot_downloads.Rd ├── get_dependencies.Rd ├── deepdep.Rd └── plot_deepdep.Rd ├── images ├── cheatsheet.pdf └── cheatsheet.pptx ├── vignettes ├── miniCRAN-1.png ├── plot_dependencies1-1.png ├── plot_dependencies1-2.png ├── plot_dependencies2-1.png ├── plot_dependencies3-1.png ├── plot_dependencies4-1.png ├── plot_dependencies5-1.png ├── precompile.R ├── deepdep-comparison.Rmd.orig └── deepdep-comparison.Rmd ├── .gitignore ├── README_files └── figure-gfm │ ├── unnamed-chunk-2-1.png │ ├── unnamed-chunk-3-1.png │ ├── unnamed-chunk-4-1.png │ └── unnamed-chunk-5-1.png ├── R ├── utils.R ├── deepdep_shiny.R ├── deepdep_declutter.R ├── print_package_description.R ├── cache_utils.R ├── api_utils.R ├── require_packages.R ├── get_downloads.R ├── get_available_packages.R ├── deepdep.R ├── plot_downloads.R ├── get_dependencies.R └── get_description.R ├── inst ├── WORDLIST └── shiny_app │ ├── ui.R │ └── server.R ├── codecov.yml ├── .Rbuildignore ├── NAMESPACE ├── appveyor.yml ├── .circleci └── config.yml ├── DESCRIPTION ├── README.rmd ├── NEWS.md └── README.md /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | tests/fixtures/**/* -diff 3 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(deepdep) 3 | 4 | test_check("deepdep") 5 | -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/images/logo.png -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/man/figures/logo.png -------------------------------------------------------------------------------- /images/cheatsheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/images/cheatsheet.pdf -------------------------------------------------------------------------------- /images/cheatsheet.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/images/cheatsheet.pptx -------------------------------------------------------------------------------- /vignettes/miniCRAN-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/vignettes/miniCRAN-1.png -------------------------------------------------------------------------------- /docs/images/cheatsheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/images/cheatsheet.pdf -------------------------------------------------------------------------------- /docs/images/cheatsheet.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/images/cheatsheet.pptx -------------------------------------------------------------------------------- /docs/reference/deepdep-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/reference/deepdep-1.png -------------------------------------------------------------------------------- /docs/reference/deepdep-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/reference/deepdep-2.png -------------------------------------------------------------------------------- /docs/reference/plot_deepdep-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/reference/plot_deepdep-1.png -------------------------------------------------------------------------------- /docs/reference/plot_deepdep-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/reference/plot_deepdep-2.png -------------------------------------------------------------------------------- /docs/reference/plot_deepdep-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/reference/plot_deepdep-3.png -------------------------------------------------------------------------------- /docs/reference/plot_deepdep-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/reference/plot_deepdep-4.png -------------------------------------------------------------------------------- /docs/reference/plot_downloads-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/reference/plot_downloads-1.png -------------------------------------------------------------------------------- /docs/reference/plot_downloads-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/reference/plot_downloads-2.png -------------------------------------------------------------------------------- /vignettes/plot_dependencies1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/vignettes/plot_dependencies1-1.png -------------------------------------------------------------------------------- /vignettes/plot_dependencies1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/vignettes/plot_dependencies1-2.png -------------------------------------------------------------------------------- /vignettes/plot_dependencies2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/vignettes/plot_dependencies2-1.png -------------------------------------------------------------------------------- /vignettes/plot_dependencies3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/vignettes/plot_dependencies3-1.png -------------------------------------------------------------------------------- /vignettes/plot_dependencies4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/vignettes/plot_dependencies4-1.png -------------------------------------------------------------------------------- /vignettes/plot_dependencies5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/vignettes/plot_dependencies5-1.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | *.Rproj 6 | doc 7 | Meta 8 | cran-comments.md 9 | CRAN-RELEASE 10 | -------------------------------------------------------------------------------- /README_files/figure-gfm/unnamed-chunk-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/README_files/figure-gfm/unnamed-chunk-2-1.png -------------------------------------------------------------------------------- /README_files/figure-gfm/unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/README_files/figure-gfm/unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /README_files/figure-gfm/unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/README_files/figure-gfm/unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /README_files/figure-gfm/unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/README_files/figure-gfm/unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /docs/README_files/figure-gfm/unnamed-chunk-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/README_files/figure-gfm/unnamed-chunk-2-1.png -------------------------------------------------------------------------------- /docs/README_files/figure-gfm/unnamed-chunk-2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/README_files/figure-gfm/unnamed-chunk-2-2.png -------------------------------------------------------------------------------- /docs/README_files/figure-gfm/unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/README_files/figure-gfm/unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /docs/README_files/figure-gfm/unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/README_files/figure-gfm/unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /docs/README_files/figure-gfm/unnamed-chunk-4-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/README_files/figure-gfm/unnamed-chunk-4-2.png -------------------------------------------------------------------------------- /docs/README_files/figure-gfm/unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/README_files/figure-gfm/unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /tests/spelling.R: -------------------------------------------------------------------------------- 1 | if(requireNamespace('spelling', quietly = TRUE)) 2 | spelling::spell_check_test(vignettes = TRUE, error = FALSE, skip_on_cran = TRUE) 3 | -------------------------------------------------------------------------------- /docs/articles/deepdep-comparison_files/figure-html/miniCRAN-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/articles/deepdep-comparison_files/figure-html/miniCRAN-1.png -------------------------------------------------------------------------------- /docs/articles/deepdep-package_files/figure-html/plot_dependencies1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/articles/deepdep-package_files/figure-html/plot_dependencies1-1.png -------------------------------------------------------------------------------- /docs/articles/deepdep-package_files/figure-html/plot_dependencies1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/articles/deepdep-package_files/figure-html/plot_dependencies1-2.png -------------------------------------------------------------------------------- /docs/articles/deepdep-package_files/figure-html/plot_dependencies2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/articles/deepdep-package_files/figure-html/plot_dependencies2-1.png -------------------------------------------------------------------------------- /docs/articles/deepdep-package_files/figure-html/plot_dependencies3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/articles/deepdep-package_files/figure-html/plot_dependencies3-1.png -------------------------------------------------------------------------------- /docs/articles/deepdep-package_files/figure-html/plot_dependencies4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/articles/deepdep-package_files/figure-html/plot_dependencies4-1.png -------------------------------------------------------------------------------- /docs/articles/deepdep-package_files/figure-html/plot_dependencies5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DominikRafacz/deepdep/HEAD/docs/articles/deepdep-package_files/figure-html/plot_dependencies5-1.png -------------------------------------------------------------------------------- /tests/testthat/setup-deepdep.R: -------------------------------------------------------------------------------- 1 | deepdep <- function(...) { 2 | reset_cached_files("ava") 3 | reset_cached_files("deps") 4 | reset_cached_files("desc") 5 | 6 | deepdep::deepdep(...) 7 | } 8 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | is_top_perc <- function(x, perc) { 2 | is_top_n(x, ceiling(perc * length(x))) 3 | } 4 | 5 | is_top_n <- function(x, n) { 6 | seq_along(x) %in% order(x, decreasing = TRUE)[seq_len(n)] 7 | } 8 | -------------------------------------------------------------------------------- /tests/testthat/setup-vcr.R: -------------------------------------------------------------------------------- 1 | if (requireNamespace("vcr", quietly = TRUE)) { 2 | library("vcr") # *Required* as vcr is set up on loading 3 | invisible(vcr::vcr_configure( 4 | dir = vcr::vcr_test_path("fixtures") 5 | )) 6 | } 7 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 2.9.2 2 | pkgdown: 1.5.1.9000 3 | pkgdown_sha: c181e5c9ac09b28974a97f5e32deddc36690fcf2 4 | articles: 5 | deepdep-comparison: deepdep-comparison.html 6 | deepdep-package: deepdep-package.html 7 | last_built: 2020-04-29T19:45Z 8 | 9 | -------------------------------------------------------------------------------- /inst/WORDLIST: -------------------------------------------------------------------------------- 1 | AppVeyor 2 | Bioc 3 | CircleCI 4 | Codecov 5 | DependenciesGraphs 6 | Github 7 | Lifecycle 8 | RCurl 9 | andrie 10 | api 11 | cranlogs 12 | datastorm 13 | dep 14 | donttest 15 | igraph 16 | md 17 | miniCRAN 18 | pkgDepTools 19 | pkgnet 20 | vactor 21 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | informational: true 10 | patch: 11 | default: 12 | target: auto 13 | threshold: 1% 14 | informational: true 15 | -------------------------------------------------------------------------------- /man/deepdep_shiny.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deepdep_shiny.R 3 | \name{deepdep_shiny} 4 | \alias{deepdep_shiny} 5 | \title{Run Shiny app} 6 | \usage{ 7 | deepdep_shiny() 8 | } 9 | \description{ 10 | This function runs shiny app that helps to produce nice deepdep plot. 11 | } 12 | -------------------------------------------------------------------------------- /tests/testthat/test-get_available_packages.R: -------------------------------------------------------------------------------- 1 | test_that("getting available packages from both local and bioc returns an error", { 2 | expect_error(get_available_packages(local = TRUE, bioc = TRUE), 3 | "You cannot use both 'local' and 'bioc' options at once.") 4 | }) 5 | 6 | test_that("chache is cleared without errors", { 7 | expect_error(get_available_packages(local = TRUE, reset_cache = TRUE), NA) 8 | }) 9 | 10 | -------------------------------------------------------------------------------- /R/deepdep_shiny.R: -------------------------------------------------------------------------------- 1 | #' @title Run Shiny app 2 | #' 3 | #' @description This function runs shiny app that helps to produce nice deepdep plot. 4 | #' 5 | #' @export 6 | deepdep_shiny <- function() { 7 | appDir <- system.file("shiny_app", package = "deepdep") 8 | if (appDir == "") { 9 | stop("Could not find example directory. Try re-installing `deepdep`.", call. = FALSE) 10 | } 11 | shiny::runApp(appDir, display.mode = "normal", launch.browser = TRUE) 12 | } 13 | -------------------------------------------------------------------------------- /tests/testthat/test-deepdep_declutter.R: -------------------------------------------------------------------------------- 1 | vcr::use_cassette("dd-declutr-R6", { 2 | dd_R6 <- deepdep("R6", depth = 3, dependency_type = "all") 3 | }) 4 | 5 | test_that("number of rows doesn't increase", { 6 | expect_lte(nrow(deepdep_declutter(dd_R6)), nrow(dd_R6)) 7 | }) 8 | 9 | test_that("no Suggests or Enhances in outer layers", { 10 | dd_R6_dcl <- deepdep_declutter(dd_R6) 11 | 12 | expect_true(all( 13 | dd_R6_dcl[dd_R6_dcl[["type"]] %in% c("Suggests", "Enhances"), "origin_level"] == 0 14 | )) 15 | }) 16 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^misc.*$ 4 | ^.travis.yml$ 5 | ^.gitignore$ 6 | ^appveyor.yml$ 7 | ^docs.*$ 8 | ^.*README.*$ 9 | ^_pkgdown\.yml$ 10 | ^codecov\.yml$ 11 | ^pkgdown.*$ 12 | ^\.circleci$ 13 | ^LICENSE.md 14 | ^CONTRIBUTING.md 15 | ^CRAN-RELEASE$ 16 | ^cran-comments\.md$ 17 | ^images.*$ 18 | README_files 19 | ^Meta$ 20 | ^.github.*$ 21 | ^vignettes/precompile\.R$ 22 | ^vignettes/.*\.Rmd\.orig$ 23 | ^inst/doc/.*\.png$ 24 | ^\.github$ 25 | ^CRAN-SUBMISSION$ 26 | ^appveyor\.yml$ 27 | ^\.circleci/config\.yml$ 28 | -------------------------------------------------------------------------------- /man/print.deepdep.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deepdep.R 3 | \name{print.deepdep} 4 | \alias{print.deepdep} 5 | \title{Print function for an object of \code{deepdep} class} 6 | \usage{ 7 | \method{print}{deepdep}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{An object of \code{deepdep} class.} 11 | 12 | \item{...}{other} 13 | } 14 | \description{ 15 | Print function for an object of \code{deepdep} class 16 | } 17 | \examples{ 18 | \donttest{ 19 | library(deepdep) 20 | 21 | dd <- deepdep("stringr") 22 | dd 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /tests/testthat/test-development.R: -------------------------------------------------------------------------------- 1 | test_that("description object has correct class", { 2 | desc <- get_description("deepdep", local = TRUE) 3 | testthat::expect_s3_class(desc, "package_description") 4 | }) 5 | 6 | test_that("dependencies object has correct class", { 7 | dep <- get_dependencies("deepdep", local = TRUE, downloads = FALSE) 8 | testthat::expect_s3_class(dep, "package_dependencies") 9 | }) 10 | 11 | test_that("deepdep object has correct class", { 12 | dd <- deepdep("deepdep", local = TRUE, ) 13 | testthat::expect_s3_class(dd, "deepdep") 14 | }) 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/articles/deepdep-package_files/header-attrs-2.1.1/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/deepdep-comparison_files/header-attrs-2.1.1/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /man/print.package_downloads.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_downloads.R 3 | \name{print.package_downloads} 4 | \alias{print.package_downloads} 5 | \title{Print function for an object of \code{package_downloads} class} 6 | \usage{ 7 | \method{print}{package_downloads}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{An object of \code{package_downloads} class.} 11 | 12 | \item{...}{other} 13 | } 14 | \description{ 15 | Print function for an object of \code{package_downloads} class 16 | } 17 | \examples{ 18 | \donttest{ 19 | library(deepdep) 20 | 21 | desc <- get_downloads("stringr") 22 | desc 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Description of a problem related to your idea** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Alternatives you've considered** 17 | If applicable, a short description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /man/print.available_packages.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_available_packages.R 3 | \name{print.available_packages} 4 | \alias{print.available_packages} 5 | \title{Print function for an object of \code{available_packages} class} 6 | \usage{ 7 | \method{print}{available_packages}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{An object of \code{available_packages} class.} 11 | 12 | \item{...}{other} 13 | } 14 | \description{ 15 | Print function for an object of \code{available_packages} class 16 | } 17 | \examples{ 18 | \donttest{ 19 | library(deepdep) 20 | 21 | av <- get_available_packages() 22 | head(av) 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /man/print.package_dependencies.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_dependencies.R 3 | \name{print.package_dependencies} 4 | \alias{print.package_dependencies} 5 | \title{Print function for an object of \code{package_dependencies} class} 6 | \usage{ 7 | \method{print}{package_dependencies}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{An object of \code{package_dependencies} class.} 11 | 12 | \item{...}{other} 13 | } 14 | \description{ 15 | Print function for an object of \code{package_dependencies} class 16 | } 17 | \examples{ 18 | \donttest{ 19 | library(deepdep) 20 | 21 | get_dependencies("htmltools", downloads = TRUE) 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /man/print.package_description.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print_package_description.R 3 | \name{print.package_description} 4 | \alias{print.package_description} 5 | \title{Print function for an object of \code{package_description} class} 6 | \usage{ 7 | \method{print}{package_description}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{An object of \code{package_description} class.} 11 | 12 | \item{...}{other} 13 | } 14 | \description{ 15 | Print function for an object of \code{package_description} class 16 | } 17 | \examples{ 18 | \donttest{ 19 | library(deepdep) 20 | 21 | description <- get_description("ggplot2") 22 | description 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /vignettes/precompile.R: -------------------------------------------------------------------------------- 1 | library(knitr) 2 | all_vignette_files <- list.files("vignettes", full.names = TRUE) 3 | vignettes_original_files <- all_vignette_files[grep("\\.orig", all_vignette_files)] 4 | 5 | for (filename in vignettes_original_files) { 6 | newname <- sub("\\.orig", "", filename) 7 | knit(filename, newname) 8 | content <- readLines(newname) 9 | writeLines(gsub('(?<= 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /R/deepdep_declutter.R: -------------------------------------------------------------------------------- 1 | deepdep_declutter <- function(dd) { 2 | depth <- max(dd[["dest_level"]]) 3 | # Remove Suggests and Enhances from outer layers 4 | dd <- dd[dd[["origin"]] == attr(dd, "package_name") | 5 | dd[["type"]] %in% match_dependency_type("strong"), ] 6 | # Recompute package distances to the center 7 | G <- igraph::graph_from_data_frame(dd) 8 | pkg_distances <- igraph::distances(G, 1, mode = "out") 9 | # Remove dependencies of packages that are at least depth away from the center 10 | pkg_to_keep <- igraph::vertex_attr(G, "name")[pkg_distances < depth] 11 | dd <- dd[dd[["origin"]] %in% pkg_to_keep, ] 12 | # Update layer positioning 13 | dd[["origin_level"]] <- pkg_distances[, dd[["origin"]]] 14 | dd[["dest_level"]] <- pkg_distances[, dd[["name"]]] 15 | 16 | attr(dd, "decluttered") <- TRUE 17 | return(dd) 18 | } 19 | -------------------------------------------------------------------------------- /R/print_package_description.R: -------------------------------------------------------------------------------- 1 | #' @title Print function for an object of \code{package_description} class 2 | #' 3 | #' @param x An object of \code{package_description} class. 4 | #' @param ... other 5 | #' 6 | #' @examples 7 | #' \donttest{ 8 | #' library(deepdep) 9 | #' 10 | #' description <- get_description("ggplot2") 11 | #' description 12 | #' } 13 | #' 14 | #' @rdname print.package_description 15 | #' @export 16 | print.package_description <- function(x, ...) { 17 | cat(x$package, ": ", x$title, "\n", sep = "") 18 | cat("Maintainer:", x$maintainer, "\n") 19 | cat("Description: \n", x$description, "\n") 20 | cat("Depends:", names(x$depends), "\n") 21 | cat("Imports:", names(x$imports), "\n") 22 | cat("LinkingTo:", names(x$linkingto), "\n") 23 | cat("Suggests:", names(x$suggests), "\n") 24 | cat("Enhances:", names(x$enhances), "\n") 25 | cat("Scrap date:", x$crandb_file_date) 26 | } 27 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(plot_dependencies,character) 4 | S3method(plot_dependencies,deepdep) 5 | S3method(plot_dependencies,default) 6 | S3method(plot_downloads,character) 7 | S3method(plot_downloads,deepdep) 8 | S3method(plot_downloads,default) 9 | S3method(plot_downloads,package_dependencies) 10 | S3method(plot_downloads,package_downloads) 11 | S3method(print,available_packages) 12 | S3method(print,deepdep) 13 | S3method(print,package_dependencies) 14 | S3method(print,package_description) 15 | S3method(print,package_downloads) 16 | export(deepdep) 17 | export(deepdep_shiny) 18 | export(get_available_packages) 19 | export(get_dependencies) 20 | export(get_description) 21 | export(get_downloads) 22 | export(plot_dependencies) 23 | export(plot_downloads) 24 | importFrom(httr,GET) 25 | importFrom(httr,content) 26 | importFrom(stats,quantile) 27 | importFrom(stats,reshape) 28 | importFrom(stats,setNames) 29 | importFrom(stats,time) 30 | importFrom(utils,available.packages) 31 | importFrom(utils,contrib.url) 32 | importFrom(utils,install.packages) 33 | importFrom(utils,menu) 34 | importFrom(utils,packageVersion) 35 | -------------------------------------------------------------------------------- /R/cache_utils.R: -------------------------------------------------------------------------------- 1 | # helper functions for get_available_packages.R and get_description.R 2 | 3 | get_cached_obj <- function(type, repo) { 4 | cache_dir <- tempdir() 5 | cache_file <- paste0(cache_dir, "/deepdep_", type, "_", repo, "_cache.RDS") 6 | if (!file.exists(cache_file) || is_too_old(cache_file)) { 7 | obj <- list() 8 | attr(obj, "type") <- type 9 | attr(obj, "repo") <- repo 10 | attr(obj, "new") <- TRUE 11 | saveRDS(obj, cache_file) 12 | obj 13 | } else { 14 | readRDS(cache_file) 15 | } 16 | } 17 | 18 | save_cache <- function(obj) { 19 | saveRDS(obj, 20 | paste0(tempdir(), "/deepdep_", attr(obj, "type"), "_", attr(obj, "repo"), "_cache.RDS")) 21 | } 22 | 23 | is_too_old <- function(file) { 24 | difftime(Sys.time(), file.info(file)$mtime, units = "secs") > 1800 25 | } 26 | 27 | reset_cached_files <- function(type) { 28 | cache_dir <- tempdir() 29 | cache_files <- paste0(cache_dir, "/deepdep_", type, "_", 30 | c("CRAN", "bioc", "local"), "_cache.RDS") 31 | for (cache_file in cache_files) { 32 | if (file.exists(cache_file)) file.remove(cache_file) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # DO NOT CHANGE the "init" and "install" sections below 2 | 3 | # Download script file from GitHub 4 | init: 5 | ps: | 6 | $ErrorActionPreference = "Stop" 7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" 8 | Import-Module '..\appveyor-tool.ps1' 9 | 10 | install: 11 | ps: Bootstrap 12 | 13 | cache: 14 | - C:\RLibrary 15 | 16 | environment: 17 | NOT_CRAN: true 18 | # env vars that may need to be set, at least temporarily, from time to time 19 | # see https://github.com/krlmlr/r-appveyor#readme for details 20 | # USE_RTOOLS: true 21 | # R_REMOTES_STANDALONE: true 22 | 23 | # Adapt as necessary starting from here 24 | 25 | build_script: 26 | - travis-tool.sh install_deps 27 | 28 | test_script: 29 | - travis-tool.sh run_tests 30 | 31 | on_failure: 32 | - 7z a failure.zip *.Rcheck\* 33 | - appveyor PushArtifact failure.zip 34 | 35 | artifacts: 36 | - path: '*.Rcheck\**\*.log' 37 | name: Logs 38 | 39 | - path: '*.Rcheck\**\*.out' 40 | name: Logs 41 | 42 | - path: '*.Rcheck\**\*.fail' 43 | name: Logs 44 | 45 | - path: '*.Rcheck\**\*.Rout' 46 | name: Logs 47 | 48 | - path: '\*_*.tar.gz' 49 | name: Bits 50 | 51 | - path: '\*_*.zip' 52 | name: Bits 53 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: rocker/verse:latest 6 | environment: 7 | R_LIBS: ~/R/Library 8 | steps: 9 | - restore_cache: 10 | keys: 11 | - r-pkg-cache-{{ arch }}-{{ .Branch }} 12 | - r-pkg-cache-{{ arch }}- 13 | - checkout 14 | - run: 15 | name: Install package dependencies 16 | command: | 17 | mkdir -p ~/R/Library 18 | Rscript -e 'install.packages("remotes")' 19 | Rscript -e 'remotes::install_deps(dependencies = TRUE, repos = c(getOption("repos"), remotes::bioc_install_repos()))' 20 | - run: 21 | name: Session information and installed package versions 22 | command: | 23 | Rscript -e 'sessionInfo()' 24 | Rscript -e 'installed.packages()[, c("Package", "Version")]' 25 | Rscript -e 'rmarkdown::pandoc_version()' 26 | - run: 27 | name: Build package 28 | command: R CMD build . 29 | - run: 30 | name: Check package 31 | command: R CMD check --as-cran --no-manual *tar.gz 32 | - store_artifacts: 33 | path: deepdep.Rcheck/ 34 | - save_cache: 35 | key: r-pkg-cache-{{ arch }}-{{ .Branch }} 36 | paths: 37 | - "~/R/Library" 38 | -------------------------------------------------------------------------------- /.github/workflows/render-rmarkdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | paths: ['README.Rmd'] 7 | 8 | name: render-readme 9 | 10 | jobs: 11 | render-rmarkdown: 12 | runs-on: ubuntu-latest 13 | env: 14 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 15 | steps: 16 | - name: Checkout repo 17 | uses: actions/checkout@v2 18 | with: 19 | fetch-depth: 0 20 | 21 | - uses: r-lib/actions/setup-pandoc@v2 22 | 23 | - uses: r-lib/actions/setup-r@v2 24 | 25 | - uses: r-lib/actions/setup-renv@v2 26 | 27 | - uses: r-lib/actions/setup-r-dependencies@v2 28 | with: 29 | extra-packages: any::pkgdown, local::. 30 | 31 | - name: Render Rmarkdown files and Commit Results 32 | run: | 33 | RMD_PATH=($(git diff --name-only ${{ github.event.before }} ${{ github.sha }} | grep '[.]Rmd$')) 34 | Rscript -e 'for (f in commandArgs(TRUE)) if (file.exists(f)) rmarkdown::render(f)' ${RMD_PATH[*]} 35 | git config --local user.name "$GITHUB_ACTOR" 36 | git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" 37 | git commit ${RMD_PATH[*]/.Rmd/.md} -m 'Re-build Rmarkdown files' || echo "No changes to commit" 38 | git push origin || echo "No changes to commit" -------------------------------------------------------------------------------- /man/get_description.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_description.R 3 | \name{get_description} 4 | \alias{get_description} 5 | \title{Scrap the DESCRIPTION file and CRAN metadata of the package} 6 | \usage{ 7 | get_description(package, bioc = FALSE, local = FALSE, reset_cache = FALSE) 8 | } 9 | \arguments{ 10 | \item{package}{A \code{character}. Name of the package that is on CRAN, Bioconductor repository or locally installed. 11 | See \code{bioc} and \code{local} arguments.} 12 | 13 | \item{bioc}{A \code{logical} value. If \code{TRUE} the Bioconductor dependencies data will be taken from the 14 | Bioconductor repository. For this option to work properly, \code{BiocManager} package needs to be installed.} 15 | 16 | \item{local}{A \code{logical} value. If \code{TRUE} only data of locally installed packages will be used (without API usage).} 17 | 18 | \item{reset_cache}{A \code{logical} value. If \code{TRUE} the cache will be cleared before obtaining the list of packages.} 19 | } 20 | \value{ 21 | An object of \code{package_description} class. 22 | } 23 | \description{ 24 | This function uses api of \href{http://crandb.r-pkg.org}{\bold{CRAN Data Base}} 25 | to scrap the DESCRIPTION file and CRAN metadata of the package. It caches the results to speed the computation process. 26 | } 27 | \examples{ 28 | library(deepdep) 29 | 30 | \donttest{ 31 | description <- get_description("ggplot2") 32 | description 33 | 34 | description_local <- get_description("deepdep", local = TRUE) 35 | description_local 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /tests/testthat/test-match_dependency_type.R: -------------------------------------------------------------------------------- 1 | test_that("using shorthand words works", { 2 | expect_identical(match_dependency_type("all"), c("Depends", "Imports", "LinkingTo", "Suggests", "Enhances")) 3 | expect_identical(match_dependency_type("most"), c("Depends", "Imports", "LinkingTo", "Suggests")) 4 | expect_identical(match_dependency_type("strong"), c("Depends", "Imports", "LinkingTo")) 5 | }) 6 | 7 | test_that("correct vector passes without a change", { 8 | vec <- c("Depends", "Suggests", "Enhances") 9 | expect_identical(vec, match_dependency_type(vec)) 10 | }) 11 | 12 | test_that("empty vector results in an error", { 13 | expect_error(match_dependency_type(c()), "'dependency_type' should specify which types of dependencies should be included") 14 | }) 15 | 16 | test_that("incorrect word results in an error", { 17 | expect_error(match_dependency_type("randomword"), "'dependency_type' should specify which types of dependencies should be included") 18 | expect_error(match_dependency_type(c("Imports", "Depends", "Enchants")), "'dependency_type' should specify which types of dependencies should be included") 19 | }) 20 | 21 | test_that("cannot mix shorthands with dependency types", { 22 | expect_error(match_dependency_type(c("strong", "Enhances")), "'dependency_type' should specify which types of dependencies should be included") 23 | }) 24 | 25 | test_that("multiple shorthands result in an error", { 26 | expect_error(match_dependency_type(c("all", "most")), "'dependency_type' should specify which types of dependencies should be included") 27 | }) 28 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [master, devel, feature/*, fix/*] 6 | pull_request: 7 | branches: [master] 8 | 9 | name: test-coverage 10 | 11 | jobs: 12 | test-coverage: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - uses: r-lib/actions/setup-r@v2 21 | with: 22 | use-public-rspm: true 23 | 24 | - uses: r-lib/actions/setup-r-dependencies@v2 25 | with: 26 | extra-packages: any::covr 27 | needs: coverage 28 | 29 | - name: Test coverage 30 | run: | 31 | covr::codecov( 32 | quiet = FALSE, 33 | clean = FALSE, 34 | install_path = file.path(Sys.getenv("RUNNER_TEMP"), "package") 35 | ) 36 | shell: Rscript {0} 37 | 38 | - name: Show testthat output 39 | if: always() 40 | run: | 41 | ## -------------------------------------------------------------------- 42 | find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \; || true 43 | shell: bash 44 | 45 | - name: Upload test results 46 | if: failure() 47 | uses: actions/upload-artifact@v3 48 | with: 49 | name: coverage-test-failures 50 | path: ${{ runner.temp }}/package 51 | -------------------------------------------------------------------------------- /R/api_utils.R: -------------------------------------------------------------------------------- 1 | #' @title Get the description file from CRAN Data Base 2 | #' 3 | #' @description [CRAN Data Base](http://crandb.r-pkg.org) 4 | #' 5 | #' @param api package name 6 | #' @param head length of head lines 7 | #' @param tail length of tail lines 8 | #' 9 | #' @noRd 10 | DB <- function(api, head = 1e6, tail = head) { 11 | ret <- paste0("http://crandb.r-pkg.org", "/", api) 12 | ret <- httr::GET(ret) 13 | ret <- httr::content(ret, as = "text", encoding = "UTF-8") 14 | ret <- jsonlite::prettify(ret) 15 | ret <- skip_lines(ret, head = head, tail = tail) 16 | 17 | ret 18 | } 19 | 20 | skip_lines <- function(text, head = 1e6, tail = 1e6) { 21 | 22 | text <- strsplit(text, "\n")[[1]] 23 | 24 | tail <- min(tail, max(0, length(text) - head)) 25 | 26 | skip_text <- if (length(text) > head + tail) { 27 | paste("\n... not showing", length(text) - head - tail, "lines ...\n") 28 | } else { 29 | character() 30 | } 31 | 32 | ret <- c(head(text, head), skip_text, tail(text, tail)) 33 | ret <- paste(ret, collapse = "\n") 34 | ret 35 | } 36 | 37 | #' @title Check if the package name is valid 38 | #' 39 | #' @param package package name 40 | #' @param bioc TRUE/FALSE 41 | #' @param local TRUE/FALSE 42 | #' 43 | #' @noRd 44 | check_package_name <- function(package, bioc, local) { 45 | if (local) { 46 | if (!is_available(package, local = TRUE)) stop(paste0(package, " is not installed")) 47 | } 48 | else if (!is_available(package, bioc)) { 49 | if (bioc) stop(paste0(package, " is not available neither on CRAN nor on Bioconductor")) 50 | else stop(paste0(package, " is not available on CRAN")) 51 | } 52 | } 53 | 54 | is_available <- function(package, bioc = FALSE, local = FALSE) { 55 | package %in% get_available_packages(bioc, local) 56 | } 57 | -------------------------------------------------------------------------------- /man/get_available_packages.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_available_packages.R 3 | \name{get_available_packages} 4 | \alias{get_available_packages} 5 | \title{Get the list of available packages} 6 | \usage{ 7 | get_available_packages(bioc = FALSE, local = FALSE, reset_cache = FALSE) 8 | } 9 | \arguments{ 10 | \item{bioc}{A \code{logical} value. If \code{TRUE} the Bioconductor dependencies data will be taken from the 11 | Bioconductor repository. For this option to work properly, \code{BiocManager} package needs to be installed.} 12 | 13 | \item{local}{A \code{logical} value. If \code{TRUE} only data of locally installed packages will be used (without API usage).} 14 | 15 | \item{reset_cache}{A \code{logical} value. If \code{TRUE} the cache will be cleared before obtaining the list of packages.} 16 | } 17 | \value{ 18 | A \code{character} vector. 19 | } 20 | \description{ 21 | Get names of packages that you have locally installed or that are available to be installed. 22 | } 23 | \details{ 24 | Function uses caching - only the first usage scraps information from servers. Those 25 | objects are then saved locally in temporary file and further usages loads needed data from the file. 26 | 27 | Arguments \code{bioc} and \code{local} cannot be \code{TRUE} simultaneously. 28 | If neither \code{local} nor \code{bioc} are \code{TRUE}, vector contains all packages available 29 | currently on CRAN. If \code{bioc} is \code{TRUE}, vector contains all packages available currently 30 | on CRAN and via Bioconductor. If \code{local} is \code{TRUE}, vactor contains all of the packages 31 | that are currently installed. 32 | } 33 | \examples{ 34 | \donttest{ 35 | 36 | library(deepdep) 37 | 38 | av <- get_available_packages() 39 | head(av) 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /inst/shiny_app/ui.R: -------------------------------------------------------------------------------- 1 | # 2 | # This is the user-interface definition of a Shiny web application. You can 3 | # run the application by clicking 'Run App' above. 4 | # 5 | # Find out more about building applications with Shiny here: 6 | # 7 | # http://shiny.rstudio.com/ 8 | # 9 | 10 | shinyUI(fluidPage( 11 | titlePanel("Deepdep Usage Example"), 12 | sidebarLayout( 13 | sidebarPanel( 14 | textInput("package", 15 | "Package to visualize:", 16 | placeholder = "package name"), 17 | radioButtons("type", 18 | "Plot type:", 19 | choices = c("Circular", "Tree"), 20 | selected = "Circular"), 21 | sliderInput("label_percentage", 22 | "Percentage of labels:", 23 | min = 0, 24 | max = 1, 25 | value = 1), 26 | sliderInput("depth", 27 | "Depth:", 28 | min = 1, 29 | max = 5, 30 | value = 1, 31 | step = 1), 32 | checkboxGroupInput("dependency_type", 33 | "Types of dependencies:", 34 | choices = c("Depends", "Imports", "Suggests", "Enhances", "LinkingTo"), 35 | selected = c("Depends", "Imports")), 36 | selectInput("options", 37 | "Additional options:", 38 | choices = list(Bioconductor = "bioc", Local = "local"), 39 | multiple = TRUE), 40 | actionButton("generate_plot", 41 | "Generate deepdep plot"), 42 | downloadButton("download", 43 | "Download plot") 44 | ), 45 | mainPanel( 46 | shinycssloaders::withSpinner(plotOutput("depPlot", click = "plot_click")) 47 | ) 48 | ) 49 | )) 50 | -------------------------------------------------------------------------------- /man/plot_downloads.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_downloads.R 3 | \name{plot_downloads} 4 | \alias{plot_downloads} 5 | \alias{plot_downloads.default} 6 | \alias{plot_downloads.deepdep} 7 | \alias{plot_downloads.package_dependencies} 8 | \alias{plot_downloads.package_downloads} 9 | \alias{plot_downloads.character} 10 | \title{Plot download count of CRAN packages.} 11 | \usage{ 12 | plot_downloads(x, ...) 13 | 14 | \method{plot_downloads}{default}(x, ...) 15 | 16 | \method{plot_downloads}{deepdep}(x, from = Sys.Date() - 365, to = Sys.Date(), ...) 17 | 18 | \method{plot_downloads}{package_dependencies}(x, from = Sys.Date() - 365, to = Sys.Date(), ...) 19 | 20 | \method{plot_downloads}{package_downloads}(x, from = Sys.Date() - 365, to = Sys.Date(), ...) 21 | 22 | \method{plot_downloads}{character}(x, from = Sys.Date() - 365, to = Sys.Date(), ...) 23 | } 24 | \arguments{ 25 | \item{x}{A \code{character} vector. Names of the packages that are on CRAN.} 26 | 27 | \item{...}{Ignored.} 28 | 29 | \item{from}{A \code{Date} class object. From which date plot the data. By default it's one year back.} 30 | 31 | \item{to}{A \code{Date} class object. To which date plot the data. By default it's now.} 32 | } 33 | \value{ 34 | A \code{ggplot2} class object. 35 | } 36 | \description{ 37 | This function uses \href{https://github.com/r-hub/cranlogs}{\bold{API}} of 38 | \href{http://cran-logs.rstudio.com/}{\bold{CRAN Logs}} to scrap the download logs of the packages and 39 | then plots the data. It works on objects of class \code{character} (vector), 40 | \code{deepdep}, \code{package_dependencies} and \code{package_downloads}. 41 | } 42 | \examples{ 43 | 44 | \donttest{ 45 | library(deepdep) 46 | 47 | plot_downloads("htmltools") 48 | 49 | dd <- deepdep("ggplot2") 50 | plot_downloads(dd) 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /inst/shiny_app/server.R: -------------------------------------------------------------------------------- 1 | # 2 | # This is the server logic of a Shiny web application. You can run the 3 | # application by clicking 'Run App' above. 4 | # 5 | # Find out more about building applications with Shiny here: 6 | # 7 | # http://shiny.rstudio.com/ 8 | # 9 | 10 | shinyServer(function(input, output, session) { 11 | dependency_plot <- eventReactive(c( 12 | input[["generate_plot"]], 13 | input[["plot_click"]] 14 | ), { 15 | plot_dependencies(input[["package"]], 16 | type = tolower(input[["type"]]), 17 | label_percentage = input[["label_percentage"]], 18 | depth = input[["depth"]], 19 | downloads = input[["label_percentage"]] != 1, 20 | bioc = "bioc" %in% input[["options"]], 21 | local = "local" %in% input[["options"]], 22 | dependency_type = input[["dependency_type"]]) 23 | }) 24 | # Maybe use `need` or `validate` here? 25 | output[["depPlot"]] <- renderPlot({ 26 | validate( 27 | need(input[["package"]], "Please pass package name.") 28 | ) 29 | dependency_plot() 30 | }) 31 | # Could we use ggsave here? 32 | output[["download"]] <- invisible(downloadHandler( 33 | filename = function() { 34 | paste0(input[["package"]], "_depth", input[["depth"]], ".png") 35 | }, 36 | content = function(file) { 37 | png(file) 38 | print(dependency_plot()) 39 | dev.off() 40 | } 41 | )) 42 | # Plot click listener 43 | observeEvent(input[["plot_click"]], { 44 | adjacency_df <- nearPoints(dependency_plot()[["data"]], input[["plot_click"]], 45 | "x", "y", addDist = TRUE, allRows = TRUE) 46 | new_package <- adjacency_df[which.min(adjacency_df[["dist_"]]), "name"] 47 | updateTextInput(session, "package", value = new_package) 48 | }) 49 | }) 50 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: deepdep 2 | Title: Visualise and Explore the Deep Dependencies of R Packages 3 | Version: 0.4.4 4 | Authors@R: c(person("Dominik", "Rafacz", email = "dominikrafacz@gmail.com", 5 | role = c("aut", "cre"), 6 | comment = c(ORCID = "0000-0003-0925-1909")), 7 | person("Hubert", "Baniecki", role = c("aut")), 8 | person("Szymon", "Maksymiuk", role = c("aut")), 9 | person("Laura", "Bakala", role = c("aut")), 10 | person("Dirk", "Eddelbuettel", role = c("ctb"))) 11 | Description: Provides tools for exploration of R package dependencies. 12 | The main deepdep() function allows to acquire deep dependencies of any package and plot them in an elegant way. 13 | It also adds some popularity measures for the packages e.g. in the form of download count through the 'cranlogs' package. 14 | Uses the CRAN metadata database and Bioconductor metadata . 15 | Other data acquire functions are: get_dependencies(), get_downloads() and get_description(). 16 | The deepdep_shiny() function runs shiny application that helps to produce a nice 'deepdep' plot. 17 | License: GPL-3 18 | Encoding: UTF-8 19 | LazyData: false 20 | RoxygenNote: 7.2.3 21 | Depends: 22 | R (>= 3.2.0) 23 | Imports: 24 | cranlogs, 25 | httr, 26 | jsonlite 27 | Suggests: 28 | BiocManager, 29 | covr, 30 | devtools, 31 | ggplot2, 32 | ggraph, 33 | graphlayouts, 34 | igraph, 35 | knitr, 36 | miniCRAN, 37 | plyr, 38 | rmarkdown, 39 | scales, 40 | shiny, 41 | shinycssloaders, 42 | spelling, 43 | stringi, 44 | testthat (>= 2.1.0), 45 | vcr 46 | VignetteBuilder: knitr 47 | URL: https://dominikrafacz.github.io/deepdep/, https://github.com/DominikRafacz/deepdep 48 | BugReports: https://github.com/DominikRafacz/deepdep/issues 49 | Language: en-GB 50 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | 6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ 7 | 8 | /* All levels of nav */ 9 | nav[data-toggle='toc'] .nav > li > a { 10 | display: block; 11 | padding: 4px 20px; 12 | font-size: 13px; 13 | font-weight: 500; 14 | color: #767676; 15 | } 16 | nav[data-toggle='toc'] .nav > li > a:hover, 17 | nav[data-toggle='toc'] .nav > li > a:focus { 18 | padding-left: 19px; 19 | color: #563d7c; 20 | text-decoration: none; 21 | background-color: transparent; 22 | border-left: 1px solid #563d7c; 23 | } 24 | nav[data-toggle='toc'] .nav > .active > a, 25 | nav[data-toggle='toc'] .nav > .active:hover > a, 26 | nav[data-toggle='toc'] .nav > .active:focus > a { 27 | padding-left: 18px; 28 | font-weight: bold; 29 | color: #563d7c; 30 | background-color: transparent; 31 | border-left: 2px solid #563d7c; 32 | } 33 | 34 | /* Nav: second level (shown on .active) */ 35 | nav[data-toggle='toc'] .nav .nav { 36 | display: none; /* Hide by default, but at >768px, show it */ 37 | padding-bottom: 10px; 38 | } 39 | nav[data-toggle='toc'] .nav .nav > li > a { 40 | padding-top: 1px; 41 | padding-bottom: 1px; 42 | padding-left: 30px; 43 | font-size: 12px; 44 | font-weight: normal; 45 | } 46 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 47 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 48 | padding-left: 29px; 49 | } 50 | nav[data-toggle='toc'] .nav .nav > .active > a, 51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 53 | padding-left: 28px; 54 | font-weight: 500; 55 | } 56 | 57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ 58 | nav[data-toggle='toc'] .nav > .active > ul { 59 | display: block; 60 | } 61 | -------------------------------------------------------------------------------- /R/require_packages.R: -------------------------------------------------------------------------------- 1 | require_packages <- function(packages, use_case = "access some functions") { 2 | installed <- vapply(packages, require_pkg, FUN.VALUE = logical(1), 3 | use_case = use_case) 4 | if (!all(installed)) { 5 | packages <- deparse(packages[!installed]) 6 | message("To ", use_case, ", install dependencies with install.packages(", packages, ").") 7 | } 8 | all(installed) 9 | } 10 | 11 | require_pkg <- function(pkg, use_case = "access some functions") { 12 | if (!is_pkg_installed(pkg) && interactive()) { 13 | install_prompt(pkg, use_case = use_case) 14 | } 15 | # Return TRUE if installation successful 16 | is_pkg_installed(pkg) 17 | } 18 | 19 | is_pkg_installed <- function(pkg) { 20 | check_pkg <- try(find.package(pkg), silent = TRUE) 21 | !inherits(check_pkg, "try-error") 22 | } 23 | 24 | #' @importFrom utils menu install.packages 25 | #' @importFrom stats setNames 26 | install_prompt <- function(pkg, use_case = "access some functions") { 27 | if (!getOption(paste0(pkg, "_suppress_prompt"), default = FALSE)) { 28 | response <- menu( 29 | c("yes", "no", "no and don't ask me anymore"), 30 | title = paste0("To ", use_case, ", you should install '", pkg, "' available on CRAN. Install?") 31 | ) 32 | switch(response, 33 | tryCatch(install.packages(pkg), 34 | finally = { 35 | if (!is_pkg_installed(pkg)) 36 | warning("There was an error during an attempt to install '", pkg, "'.", call. = FALSE) 37 | }), 38 | message("You cannot access full functionality of this package without having installed '", pkg, "' first. "), 39 | { 40 | options(setNames(list(TRUE), paste0(pkg, "_suppress_prompt"))) 41 | cat("Ok, but you cannot access full functionality of this package without having installed '", pkg, "' first.", 42 | sep = "") 43 | }, 44 | message("You cannot access full functionality of this package without having installed '", pkg, "' first. ")) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /man/get_dependencies.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_dependencies.R 3 | \name{get_dependencies} 4 | \alias{get_dependencies} 5 | \title{Acquire the dependencies of the package} 6 | \usage{ 7 | get_dependencies( 8 | package, 9 | downloads = TRUE, 10 | bioc = FALSE, 11 | local = FALSE, 12 | dependency_type = "strong" 13 | ) 14 | } 15 | \arguments{ 16 | \item{package}{A \code{character}. Name of the package that is on CRAN, Bioconductor repository or locally installed. 17 | See \code{bioc} and \code{local} arguments.} 18 | 19 | \item{downloads}{A \code{logical}. If \code{TRUE} add package downloads data. By default it's \code{TRUE}.} 20 | 21 | \item{bioc}{A \code{logical} value. If \code{TRUE} the Bioconductor dependencies data will be taken from the 22 | Bioconductor repository. For this option to work properly, \code{BiocManager} package needs to be installed.} 23 | 24 | \item{local}{A \code{logical} value. If \code{TRUE} only data of locally installed packages will be used (without API usage).} 25 | 26 | \item{dependency_type}{A \code{character} vector. Types of the dependencies that should be sought, a subset of 27 | \code{c("Imports", "Depends", "LinkingTo", "Suggests", "Enhances")}. Other possibilities are: character string 28 | \code{"all"}, a shorthand for the whole vector; character string \code{"most"} for the same vector without \code{"Enhances"}; 29 | character string \code{"strong"} (default) for the first three elements of that vector. Works analogously to 30 | \code{\link[tools]{package_dependencies}}.} 31 | } 32 | \value{ 33 | An object of \code{package_dependencies} class. 34 | } 35 | \description{ 36 | This function uses \code{\link{get_description}} and \code{\link{get_downloads}} 37 | to acquire the dependencies of the package (with their downloads). 38 | } 39 | \examples{ 40 | library(deepdep) 41 | 42 | \donttest{ 43 | dependencies <- get_dependencies("htmltools", downloads = FALSE) 44 | dependencies 45 | 46 | dependencies_local <- get_dependencies("deepdep", downloads = FALSE, local = TRUE) 47 | dependencies_local 48 | } 49 | 50 | } 51 | \seealso{ 52 | \code{\link{get_description}} \code{\link{get_downloads}} 53 | } 54 | -------------------------------------------------------------------------------- /man/deepdep.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deepdep.R 3 | \name{deepdep} 4 | \alias{deepdep} 5 | \title{Acquire the dependencies of the package on any depth level} 6 | \usage{ 7 | deepdep( 8 | package, 9 | depth = 1, 10 | downloads = FALSE, 11 | bioc = FALSE, 12 | local = FALSE, 13 | dependency_type = "strong" 14 | ) 15 | } 16 | \arguments{ 17 | \item{package}{A \code{character}. Name of the package that is on CRAN, Bioconductor repository or locally installed. 18 | See \code{bioc} and \code{local} arguments.} 19 | 20 | \item{depth}{An \code{integer}. Maximum depth level of the dependency. By default it's \code{1}.} 21 | 22 | \item{downloads}{A \code{logical}. If \code{TRUE} add dependency downloads data. By default it's \code{FALSE}.} 23 | 24 | \item{bioc}{A \code{logical} value. If \code{TRUE} the Bioconductor dependencies data will be taken from the 25 | Bioconductor repository. For this option to work properly, \code{BiocManager} package needs to be installed.} 26 | 27 | \item{local}{A \code{logical} value. If \code{TRUE} only data of locally installed packages will be used (without API usage).} 28 | 29 | \item{dependency_type}{A \code{character} vector. Types of the dependencies that should be sought, a subset of 30 | \code{c("Imports", "Depends", "LinkingTo", "Suggests", "Enhances")}. Other possibilities are: character string 31 | \code{"all"}, a shorthand for the whole vector; character string \code{"most"} for the same vector without \code{"Enhances"}; 32 | character string \code{"strong"} (default) for the first three elements of that vector. Works analogously to 33 | \code{\link[tools]{package_dependencies}}.} 34 | } 35 | \value{ 36 | An object of \code{deepdep} class. 37 | } 38 | \description{ 39 | This function is an ultimate wrapper for \code{\link{get_dependencies}}. It inherits all of the arguments and 40 | allows to recursively search for the dependencies at the higher level of \code{depth}. 41 | } 42 | \examples{ 43 | 44 | \donttest{ 45 | library(deepdep) 46 | 47 | dd_downloads <- deepdep("ggplot2") 48 | head(dd_downloads) 49 | 50 | dd_2 <- deepdep("ggplot2", depth = 2, downloads = TRUE) 51 | plot_dependencies(dd_2, "circular") 52 | 53 | dd_local <- deepdep("deepdep", local = TRUE) 54 | plot_dependencies(dd_local) 55 | } 56 | 57 | 58 | } 59 | \seealso{ 60 | \code{\link{get_dependencies}} 61 | } 62 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /R/get_downloads.R: -------------------------------------------------------------------------------- 1 | #' @title Scrap the download data of the package 2 | #' 3 | #' @description This function uses \href{https://github.com/r-hub/cranlogs}{\bold{API}} of 4 | #' \href{http://cran-logs.rstudio.com/}{\bold{CRAN Logs}} to scrap the download logs of the package. 5 | #' 6 | #' @param package A \code{character}. Name of the package that is on CRAN. 7 | #' 8 | #' @return An object of \code{package_downloads} class. 9 | #' 10 | #' 11 | #' @examples 12 | #' \donttest{ 13 | #' library(deepdep) 14 | #' 15 | #' downloads <- get_downloads("ggplot2") 16 | #' downloads 17 | #' } 18 | #' 19 | #' 20 | #' @export 21 | get_downloads <- function(package) { 22 | 23 | if (!is_available(package)) return(NULL) 24 | 25 | # use the `cranlogs` package for the querry (from offical cran downloads data) 26 | # count from 2012-10-01 - date of first entry "http://cran-logs.rstudio.com/" 27 | downloads <- cranlogs::cran_downloads(package, from = "2012-10-01", to = Sys.Date()) 28 | 29 | # remove zeros from last few days without data 30 | downloads_count <- rev(downloads$count) 31 | 32 | # first two entries are 0 33 | # downloads_count <- downloads_count[which(downloads_count != 0)[1]:length(downloads_count)] 34 | 35 | downloads_count <- downloads_count[3:length(downloads_count)] 36 | 37 | # take count from last day that was not 0 ( cran_downloads(when = "last-day") ) 38 | last_day <- downloads_count[1] 39 | last_week <- sum(downloads_count[1:7]) 40 | last_month <- sum(downloads_count[1:30]) 41 | last_quarter <- sum(downloads_count[1:91]) 42 | last_half <- sum(downloads_count[1:182]) 43 | grand_total <- sum(downloads_count) 44 | 45 | 46 | ret <- c("last_day" = last_day, "last_week" = last_week, "last_month" = last_month, 47 | "last_quarter" = last_quarter, "last_half" = last_half, "grand_total" = grand_total) 48 | 49 | attr(ret, "package_name") <- package 50 | class(ret) <- c("package_downloads", "numeric") 51 | ret 52 | } 53 | 54 | #' @title Print function for an object of \code{package_downloads} class 55 | #' 56 | #' @param x An object of \code{package_downloads} class. 57 | #' @param ... other 58 | #' 59 | #' 60 | #' @examples 61 | #' \donttest{ 62 | #' library(deepdep) 63 | #' 64 | #' desc <- get_downloads("stringr") 65 | #' desc 66 | #' } 67 | #' 68 | #' @rdname print.package_downloads 69 | #' @export 70 | print.package_downloads <- function(x, ...) { 71 | print(as.data.frame(x)) 72 | } 73 | -------------------------------------------------------------------------------- /tests/testthat/test-deepdep.R: -------------------------------------------------------------------------------- 1 | # wrapper for avoiding build version mismatches when querying Bioc 2 | deepdep_wrapped <- function(...) { 3 | tryCatch(deepdep(...), 4 | error = function(err) { 5 | if (grepl("Bioconductor version '[0-9\\.]*' requires R version '[0-9\\.]*'", 6 | err$message) || 7 | grepl("Bioconductor does not yet build and check packages for R version [0-9\\.]*", 8 | err$message)) 9 | skip("Build's Bioconductor and R version mismatch makes performing test impossible") 10 | else stop(err$message) 11 | }) 12 | } 13 | 14 | test_that("obtaining local dependencies returns objects of correct types", { 15 | dd <- deepdep("deepdep", local = TRUE, depth = 1, dependency_type = c("Depends", "Imports", "LinkingTo", "Suggests")) 16 | expect_is(dd, "deepdep") 17 | }) 18 | 19 | test_that("using shorthand parameters returns the same result", { 20 | dd <- deepdep("deepdep", local = TRUE, depth = 1, dependency_type = c("Depends", "Imports", "LinkingTo", "Suggests")) 21 | dd2 <- deepdep("deepdep", local = TRUE, depth = 1, dependency_type = "most") 22 | expect_identical(dd, dd2) 23 | }) 24 | 25 | test_that("obtaining Bioc dependencies returns objects of correct types", { 26 | skip_if_not_installed("vcr") 27 | 28 | reset_cached_files("ava") 29 | reset_cached_files("deps") 30 | reset_cached_files("desc") 31 | 32 | vcr::use_cassette("deepdep-1", { 33 | dd <- deepdep_wrapped("les", downloads = FALSE, bioc = TRUE, depth = 1, 34 | dependency_type = c("Depends", "Imports", "Enhances", "LinkingTo")) 35 | }, serialize_with = "json") 36 | 37 | expect_is(dd, "deepdep") 38 | }) 39 | 40 | test_that("incorrect combination of parameters results in error",{ 41 | expect_error(deepdep_wrapped("ggforce", downloads = TRUE, local = FALSE, bioc = TRUE, depth = 2, dependency_type = c("Depends", "Imports"))) 42 | expect_error(deepdep_wrapped("ggforce", downloads = TRUE, local = TRUE, bioc = TRUE, depth = 2, dependency_type = c("Depends", "Imports"))) 43 | expect_error(deepdep_wrapped("ggforce", downloads = FALSE, local = TRUE, bioc = TRUE, depth = 2, dependency_type = c("Depends", "Imports"))) 44 | expect_error(deepdep("ggforce", downloads = TRUE, local = TRUE, bioc = FALSE, depth = 2, dependency_type = c("Depends", "Imports"))) 45 | }) 46 | 47 | test_that("packages with no dependencies return empty deepdep object in result", { 48 | skip_if_not_installed("vcr") 49 | 50 | reset_cached_files("ava") 51 | reset_cached_files("deps") 52 | reset_cached_files("desc") 53 | 54 | vcr::use_cassette("deepdep-2", { 55 | dd <- deepdep("rlang") 56 | expect_equal(nrow(dd), 0) 57 | }) 58 | }) 59 | -------------------------------------------------------------------------------- /R/get_available_packages.R: -------------------------------------------------------------------------------- 1 | #' @title Get the list of available packages 2 | #' 3 | #' @description Get names of packages that you have locally installed or that are available to be installed. 4 | #' 5 | #' @param bioc A \code{logical} value. If \code{TRUE} the Bioconductor dependencies data will be taken from the 6 | #' Bioconductor repository. For this option to work properly, \code{BiocManager} package needs to be installed. 7 | #' @param local A \code{logical} value. If \code{TRUE} only data of locally installed packages will be used (without API usage). 8 | #' @param reset_cache A \code{logical} value. If \code{TRUE} the cache will be cleared before obtaining the list of packages. 9 | #' 10 | #' @return A \code{character} vector. 11 | #' 12 | #' @details Function uses caching - only the first usage scraps information from servers. Those 13 | #' objects are then saved locally in temporary file and further usages loads needed data from the file. 14 | #' 15 | #' Arguments \code{bioc} and \code{local} cannot be \code{TRUE} simultaneously. 16 | #' If neither \code{local} nor \code{bioc} are \code{TRUE}, vector contains all packages available 17 | #' currently on CRAN. If \code{bioc} is \code{TRUE}, vector contains all packages available currently 18 | #' on CRAN and via Bioconductor. If \code{local} is \code{TRUE}, vactor contains all of the packages 19 | #' that are currently installed. 20 | #' 21 | #' @examples 22 | #' \donttest{ 23 | #' 24 | #' library(deepdep) 25 | #' 26 | #' av <- get_available_packages() 27 | #' head(av) 28 | #' 29 | #' } 30 | #' 31 | #' @export 32 | get_available_packages <- function(bioc = FALSE, local = FALSE, reset_cache = FALSE) { 33 | if (local && bioc) stop("You cannot use both 'local' and 'bioc' options at once.") 34 | if (reset_cache) reset_cached_files("ava") 35 | if (local) return(get_available_packages_cached("local")) 36 | if (bioc) get_available_packages_cached("bioc") 37 | else get_available_packages_cached("CRAN") 38 | } 39 | 40 | #' @importFrom utils available.packages contrib.url 41 | get_available_packages_cached <- function(repo) { 42 | pkgs <- get_cached_obj("ava", repo) 43 | if (attr(pkgs, "new")) { 44 | pkgs <- switch(repo, 45 | CRAN = available.packages( 46 | contriburl = contrib.url("https://cloud.r-project.org/"))[, 1], 47 | bioc = {BiocManager::available()}, 48 | local = list.dirs(.libPaths()[1], full.names = FALSE, recursive = FALSE) 49 | ) 50 | attr(pkgs, "type") <- "ava" 51 | attr(pkgs, "repo") <- repo 52 | attr(pkgs, "new") <- FALSE 53 | save_cache(pkgs) 54 | } 55 | class(pkgs) <- c("character", "available_packages") 56 | pkgs 57 | } 58 | 59 | 60 | #' @title Print function for an object of \code{available_packages} class 61 | #' 62 | #' @param x An object of \code{available_packages} class. 63 | #' @param ... other 64 | #' 65 | #' @examples 66 | #' \donttest{ 67 | #' library(deepdep) 68 | #' 69 | #' av <- get_available_packages() 70 | #' head(av) 71 | #' } 72 | #' 73 | #' @rdname print.available_packages 74 | #' @export 75 | print.available_packages <- function(x, ...) { 76 | attributes(x) <- NULL 77 | x <- unname(x) 78 | print(x) 79 | } 80 | -------------------------------------------------------------------------------- /README.rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | # Visualise and Explore Deep Dependencies of R Packages 6 | 7 | 8 | [![CRAN status](https://www.r-pkg.org/badges/version/deepdep)](https://CRAN.R-project.org/package=deepdep) 9 | [![CircleCI build status](https://circleci.com/gh/DominikRafacz/deepdep.svg?style=svg)](https://circleci.com/gh/DominikRafacz/deepdep) 10 | [![AppVeyor build status](https://ci.appveyor.com/api/projects/status/github/DominikRafacz/deepdep?branch=master&svg=true)](https://ci.appveyor.com/project/DominikRafacz/deepdep) 11 | [![Codecov test coverage](https://codecov.io/gh/DominikRafacz/deepdep/branch/master/graph/badge.svg)](https://codecov.io/gh/DominikRafacz/deepdep?branch=master) 12 | [![Lifecycle: maturing](https://img.shields.io/badge/lifecycle-maturing-blue.svg)](https://www.tidyverse.org/lifecycle/#maturing) 13 | 14 | 15 | 16 | ## Overview 17 | 18 | The `deepdep` package provides tools for exploration of package dependencies. The main `deepdep()` function allows to acquire deep dependencies of any package and plot them in an elegant way. It also adds some popularity measures for the packages e.g. in the form of download count through the `cranlogs` package. Uses the [CRAN metadata database](http://crandb.r-pkg.org) and [Bioconductor metadata](http://bioconductor.org). 19 | 20 | **Exploration tools:** 21 | 22 | - `deepdep()` 23 | - `get_dependencies()` 24 | - `get_downloads()` 25 | - `get_description()` 26 | 27 | **Visualisation tools:** 28 | 29 | - `plot_dependencies()` 30 | - `plot_downloads()` 31 | - `deepdep_shiny()` runs shiny application that helps to produce a nice **deepdep plot** 32 | 33 | ## Installation 34 | 35 | ```{r eval = FALSE} 36 | # Install from CRAN: 37 | install.packages("deepdep") 38 | 39 | # Install the development version from GitHub: 40 | devtools::install_github("DominikRafacz/deepdep") 41 | ``` 42 | 43 | ## Examples [**introduction to the deepdep package**](https://dominikrafacz.github.io/deepdep/articles/deepdep-package.html) 44 | 45 | ```{r set-options, echo=FALSE, cache=FALSE} 46 | options(width = 700) 47 | ``` 48 | 49 | ```{r message=FALSE, warning=FALSE, fig.width=10, fig.height=7, fig.align='center'} 50 | library(deepdep) 51 | 52 | dd <- deepdep("ggplot2", depth = 2) 53 | 54 | head(dd) 55 | 56 | plot_dependencies(dd, "circular") 57 | ``` 58 | 59 | ```{r message=FALSE, warning=FALSE, fig.width=10, fig.height=7, fig.align='center'} 60 | plot_dependencies("bayes4psy", show_version = TRUE, 61 | dependency_type = c("Depends", "Imports", "Suggests", "LinkingTo")) 62 | ``` 63 | 64 | ```{r message=FALSE, warning=FALSE, fig.width=8, fig.height=6, fig.align='center'} 65 | dd_xgboost <- deepdep("xgboost", dependency_type = "Imports", downloads = TRUE) 66 | 67 | head(dd_xgboost) 68 | 69 | plot_downloads(dd_xgboost) 70 | ``` 71 | 72 | ```{r message=FALSE, warning=FALSE, fig.width=8, fig.height=5, fig.align='center'} 73 | plot_dependencies(dd_xgboost, "tree", show_version = TRUE) 74 | ``` 75 | 76 | 79 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # deepdep 0.4.4 2 | * fixed failing tests caused by new version of vcr package 3 | 4 | # deepdep 0.4.3 5 | * fixed bug related to change in how indexing of data frame is performed 6 | 7 | # deepdep 0.4.2 8 | * fixed bug caused by breaking change in `igraph` related to assigning attributes to graph nodes (issue #51) 9 | * fixed bug which made plots unable to be rendered when there are no dependencies 10 | 11 | # deepdep 0.4.1 12 | * fixed bug where `plot_dependencies()` wouldn't remove all invalid dependencies when using `declutter = TRUE` (issue #35) 13 | * fixed bug where `plot_dependencies()` would sometimes raise an error when using `show_version = TRUE` and `depth >= 2` (issue #36) 14 | * fixed bug where `plot_dependencies()` would plot one non-central label even when using `label_percentage = 0` (issue #38) 15 | * tests that use CRAN download counts now skip on CRAN only 16 | 17 | # deepdep 0.4.0 18 | * removed hard dependencies on plotting-related packages; `ggplot2`, `ggraph`, `graphlayouts`, `igraph`, and `scales` are now Suggests instead of Imports (issue #32) 19 | * removed unused dependency on `ggforce` 20 | * added `declutter` parameter for `plot_dependencies()` that allows for ignoring non-strong dependencies of Suggests while plotting (issue #27) 21 | * `vcr` package is now optional for running tests (pull request #26) 22 | 23 | # deepdep 0.3.1 24 | * adjusted parameter of `deepdep` function similarly to `get_dependencies` (issue #24) 25 | 26 | # deepdep 0.3.0 27 | * adjusted `dependency_type` argument to be consistent with `tools` package (issue #19) 28 | * added `show_stamp` parameter for plot function (issue #20) 29 | 30 | # deepdep 0.2.5 31 | * wrapped `deepdep` in tests with `tryCatch` in case of R-devel and Bioc-devel versions mismatch 32 | * marked all non-local examples with "donttest" 33 | * adjusted to new version of the `vcr` package 34 | 35 | # deepdep 0.2.2 -- 0.2.4 36 | * this versions are attempts to eliminating all possible errors during checks associated with problems with internet connection: this consists of marking time-consuming examples by "donttest" in the documentation, using the `vcr` package to mock up api queries and creating pre-compiled vignettes 37 | 38 | # deepdep 0.2.1 39 | * fixed an error in `deepdep` that caused dependencies of one package to be added to the result many times 40 | * the way in which dependency layers are created during plotting has been improved 41 | * added columns in `deepdep` object, informing in which dependency layers the source and target packages are located 42 | * allowed more than five layers of dependencies on plot created by `plot_dependencies()` 43 | * fixed bugs caused by `plot_dependencies()` used with `label_percentage` parameter 44 | * `plot_dependencies()` used with `label_percentage` parameter now shows small dots whenever package has not enough downloads to be plotted with label (instead of empty labels, as previously) 45 | 46 | # deepdep 0.2.0 47 | * CRAN version 48 | 49 | # deepdep 0.1.1 50 | * renamed `deps_types` argument to `dependency_type` 51 | * added shiny app that generates `deepdep` plot 52 | 53 | # deepdep 0.1.0 54 | * first stable version of the `deepdep` package 55 | * implemented functions: `deepdep()`, `get_available_packages()`, `get_dependencies()`, 56 | `get_description()`, `get_downloads()`, `plot_dependencies()` 57 | 58 | -------------------------------------------------------------------------------- /.github/workflows/rhub.yaml: -------------------------------------------------------------------------------- 1 | # R-hub's generic GitHub Actions workflow file. It's canonical location is at 2 | # https://github.com/r-hub/actions/blob/v1/workflows/rhub.yaml 3 | # You can update this file to a newer version using the rhub2 package: 4 | # 5 | # rhub::rhub_setup() 6 | # 7 | # It is unlikely that you need to modify this file manually. 8 | 9 | name: R-hub 10 | run-name: "${{ github.event.inputs.id }}: ${{ github.event.inputs.name || format('Manually run by {0}', github.triggering_actor) }}" 11 | 12 | on: 13 | workflow_dispatch: 14 | inputs: 15 | config: 16 | description: 'A comma separated list of R-hub platforms to use.' 17 | type: string 18 | default: 'linux,windows,macos' 19 | name: 20 | description: 'Run name. You can leave this empty now.' 21 | type: string 22 | id: 23 | description: 'Unique ID. You can leave this empty now.' 24 | type: string 25 | 26 | jobs: 27 | 28 | setup: 29 | runs-on: ubuntu-latest 30 | outputs: 31 | containers: ${{ steps.rhub-setup.outputs.containers }} 32 | platforms: ${{ steps.rhub-setup.outputs.platforms }} 33 | 34 | steps: 35 | # NO NEED TO CHECKOUT HERE 36 | - uses: r-hub/actions/setup@v1 37 | with: 38 | config: ${{ github.event.inputs.config }} 39 | id: rhub-setup 40 | 41 | linux-containers: 42 | needs: setup 43 | if: ${{ needs.setup.outputs.containers != '[]' }} 44 | runs-on: ubuntu-latest 45 | name: ${{ matrix.config.label }} 46 | strategy: 47 | fail-fast: false 48 | matrix: 49 | config: ${{ fromJson(needs.setup.outputs.containers) }} 50 | container: 51 | image: ${{ matrix.config.container }} 52 | 53 | steps: 54 | - uses: r-hub/actions/checkout@v1 55 | - uses: r-hub/actions/platform-info@v1 56 | with: 57 | token: ${{ secrets.RHUB_TOKEN }} 58 | job-config: ${{ matrix.config.job-config }} 59 | - uses: r-hub/actions/setup-deps@v1 60 | with: 61 | token: ${{ secrets.RHUB_TOKEN }} 62 | job-config: ${{ matrix.config.job-config }} 63 | - uses: r-hub/actions/run-check@v1 64 | with: 65 | token: ${{ secrets.RHUB_TOKEN }} 66 | job-config: ${{ matrix.config.job-config }} 67 | 68 | other-platforms: 69 | needs: setup 70 | if: ${{ needs.setup.outputs.platforms != '[]' }} 71 | runs-on: ${{ matrix.config.os }} 72 | name: ${{ matrix.config.label }} 73 | strategy: 74 | fail-fast: false 75 | matrix: 76 | config: ${{ fromJson(needs.setup.outputs.platforms) }} 77 | 78 | steps: 79 | - uses: r-hub/actions/checkout@v1 80 | - uses: r-hub/actions/setup-r@v1 81 | with: 82 | job-config: ${{ matrix.config.job-config }} 83 | token: ${{ secrets.RHUB_TOKEN }} 84 | - uses: r-hub/actions/platform-info@v1 85 | with: 86 | token: ${{ secrets.RHUB_TOKEN }} 87 | job-config: ${{ matrix.config.job-config }} 88 | - uses: r-hub/actions/setup-deps@v1 89 | with: 90 | job-config: ${{ matrix.config.job-config }} 91 | token: ${{ secrets.RHUB_TOKEN }} 92 | - uses: r-hub/actions/run-check@v1 93 | with: 94 | job-config: ${{ matrix.config.job-config }} 95 | token: ${{ secrets.RHUB_TOKEN }} 96 | -------------------------------------------------------------------------------- /tests/fixtures/deepdep-2.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: http://crandb.r-pkg.org/rlang 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | Accept: application/json, text/xml, application/xml, */* 10 | response: 11 | status: 12 | status_code: 200 13 | category: Success 14 | reason: OK 15 | message: 'Success: (200) OK' 16 | headers: 17 | date: Mon, 20 Feb 2023 09:44:02 GMT 18 | content-type: application/json 19 | transfer-encoding: chunked 20 | connection: keep-alive 21 | etag: W/"8M5BHOYFM4TSUL788BQRWYN0S" 22 | vary: Accept 23 | x-couch-request-id: 139565d00f 24 | x-couchdb-body-time: '0' 25 | cf-cache-status: DYNAMIC 26 | report-to: '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=GJieOZriPexQwkurD3H0Z3LdxP55O%2B9MJ2xwTmpqWWpk4Sgz5qUXxAPEKBSLEdtKczUwdYsAwXSp9e0RUuJYRS6yomtHp3ktWZZ27siuBQ7Iz6MRrSPGIpvXN%2BTqigAK%2F9oy"}],"group":"cf-nel","max_age":604800}' 27 | nel: '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}' 28 | server: cloudflare 29 | cf-ray: 79c64d27d8ac3570-WAW 30 | content-encoding: gzip 31 | alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400 32 | body: 33 | encoding: '' 34 | file: no 35 | string: '{"Package":"rlang","Version":"1.0.6","Title":"Functions for Base Types 36 | and Core R and ''Tidyverse'' Features","Description":"A toolbox for working 37 | with base types, core R features\u000alike the condition system, and core 38 | ''Tidyverse'' features like tidy\u000aevaluation.","Authors@R":"c(\u000aperson(\"Lionel\", 39 | \"Henry\", ,\"lionel@rstudio.com\", c(\"aut\", \"cre\")),\u000aperson(\"Hadley\", 40 | \"Wickham\", ,\"hadley@rstudio.com\", \"aut\"),\u000aperson(given = \"mikefc\",\u000aemail 41 | = \"mikefc@coolbutuseless.com\",\u000arole = \"cph\",\u000acomment = \"Hash 42 | implementation based on Mike''s xxhashlite\"),\u000aperson(given = \"Yann\",\u000afamily 43 | = \"Collet\",\u000arole = \"cph\",\u000acomment = \"Author of the embedded 44 | xxHash library\"),\u000aperson(given = \"RStudio\", role = c(\"cph\", \"fnd\"))\u000a)","License":"MIT 45 | + file LICENSE","ByteCompile":"true","Biarch":"true","Depends":{"R":">= 3.4.0"},"Imports":{"utils":"*"},"Suggests":{"cli":">= 46 | 3.1.0","covr":"*","crayon":"*","fs":"*","glue":"*","knitr":"*","magrittr":"*","methods":"*","pillar":"*","rmarkdown":"*","stats":"*","testthat":">= 47 | 3.0.0","tibble":"*","usethis":"*","vctrs":">= 0.2.3","withr":"*"},"Enhances":{"winch":"*"},"SystemRequirements":"C++11","Encoding":"UTF-8","RoxygenNote":"7.2.1.9000","URL":"https://rlang.r-lib.org, 48 | https://github.com/r-lib/rlang","BugReports":"https://github.com/r-lib/rlang/issues","Config/testthat/edition":"3","Config/Needs/website":"dplyr, 49 | tidyverse/tidytemplate","NeedsCompilation":"yes","Packaged":"2022-09-23 16:12:48 50 | UTC; lionel","Author":"Lionel Henry [aut, cre],\u000aHadley Wickham [aut],\u000amikefc 51 | [cph] (Hash implementation based on Mike''s xxhashlite),\u000aYann Collet 52 | [cph] (Author of the embedded xxHash library),\u000aRStudio [cph, fnd]","Maintainer":"Lionel 53 | Henry ","Repository":"CRAN","Date/Publication":"2022-09-24 54 | 05:40:02 UTC","crandb_file_date":"2022-09-24 06:56:45","MD5sum":"907bc04039194b0c7edc19e9084b14fc","date":"2022-09-24T04:40:02+00:00","releases":[]}' 55 | recorded_at: 2023-02-20 09:44:02 GMT 56 | recorded_with: vcr/1.2.0, webmockr/0.8.2 57 | -------------------------------------------------------------------------------- /tests/fixtures/plot-dd-rlang.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: http://crandb.r-pkg.org/rlang 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | Accept: application/json, text/xml, application/xml, */* 10 | response: 11 | status: 12 | status_code: 200 13 | category: Success 14 | reason: OK 15 | message: 'Success: (200) OK' 16 | headers: 17 | date: Mon, 20 Feb 2023 09:44:24 GMT 18 | content-type: application/json 19 | transfer-encoding: chunked 20 | connection: keep-alive 21 | etag: W/"8M5BHOYFM4TSUL788BQRWYN0S" 22 | vary: Accept 23 | x-couch-request-id: 70162060c4 24 | x-couchdb-body-time: '0' 25 | cf-cache-status: DYNAMIC 26 | report-to: '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=rCaZ9MrPl7XXtTRIG5OImWzT7xm2SsuK%2Bg%2FXSQLDJZgsvwcot%2Fe2wBP9NSK9f6lgDyS9nZDn8%2B%2Fzi0trgIv2QSCfmWE093fNw2QIcxG3ekLL0Km5lQWGxCzaMU1omF%2FDO61z"}],"group":"cf-nel","max_age":604800}' 27 | nel: '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}' 28 | server: cloudflare 29 | cf-ray: 79c64db35c973570-WAW 30 | content-encoding: gzip 31 | alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400 32 | body: 33 | encoding: '' 34 | file: no 35 | string: '{"Package":"rlang","Version":"1.0.6","Title":"Functions for Base Types 36 | and Core R and ''Tidyverse'' Features","Description":"A toolbox for working 37 | with base types, core R features\u000alike the condition system, and core 38 | ''Tidyverse'' features like tidy\u000aevaluation.","Authors@R":"c(\u000aperson(\"Lionel\", 39 | \"Henry\", ,\"lionel@rstudio.com\", c(\"aut\", \"cre\")),\u000aperson(\"Hadley\", 40 | \"Wickham\", ,\"hadley@rstudio.com\", \"aut\"),\u000aperson(given = \"mikefc\",\u000aemail 41 | = \"mikefc@coolbutuseless.com\",\u000arole = \"cph\",\u000acomment = \"Hash 42 | implementation based on Mike''s xxhashlite\"),\u000aperson(given = \"Yann\",\u000afamily 43 | = \"Collet\",\u000arole = \"cph\",\u000acomment = \"Author of the embedded 44 | xxHash library\"),\u000aperson(given = \"RStudio\", role = c(\"cph\", \"fnd\"))\u000a)","License":"MIT 45 | + file LICENSE","ByteCompile":"true","Biarch":"true","Depends":{"R":">= 3.4.0"},"Imports":{"utils":"*"},"Suggests":{"cli":">= 46 | 3.1.0","covr":"*","crayon":"*","fs":"*","glue":"*","knitr":"*","magrittr":"*","methods":"*","pillar":"*","rmarkdown":"*","stats":"*","testthat":">= 47 | 3.0.0","tibble":"*","usethis":"*","vctrs":">= 0.2.3","withr":"*"},"Enhances":{"winch":"*"},"SystemRequirements":"C++11","Encoding":"UTF-8","RoxygenNote":"7.2.1.9000","URL":"https://rlang.r-lib.org, 48 | https://github.com/r-lib/rlang","BugReports":"https://github.com/r-lib/rlang/issues","Config/testthat/edition":"3","Config/Needs/website":"dplyr, 49 | tidyverse/tidytemplate","NeedsCompilation":"yes","Packaged":"2022-09-23 16:12:48 50 | UTC; lionel","Author":"Lionel Henry [aut, cre],\u000aHadley Wickham [aut],\u000amikefc 51 | [cph] (Hash implementation based on Mike''s xxhashlite),\u000aYann Collet 52 | [cph] (Author of the embedded xxHash library),\u000aRStudio [cph, fnd]","Maintainer":"Lionel 53 | Henry ","Repository":"CRAN","Date/Publication":"2022-09-24 54 | 05:40:02 UTC","crandb_file_date":"2022-09-24 06:56:45","MD5sum":"907bc04039194b0c7edc19e9084b14fc","date":"2022-09-24T04:40:02+00:00","releases":[]}' 55 | recorded_at: 2023-02-20 09:44:25 GMT 56 | recorded_with: vcr/1.2.0, webmockr/0.8.2 57 | -------------------------------------------------------------------------------- /man/plot_deepdep.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot_deepdep.R 3 | \name{plot_dependencies} 4 | \alias{plot_dependencies} 5 | \alias{plot_dependencies.default} 6 | \alias{plot_dependencies.character} 7 | \alias{plot_dependencies.deepdep} 8 | \title{Main plot function for a \code{deepdep} object} 9 | \usage{ 10 | plot_dependencies( 11 | x, 12 | type = "circular", 13 | same_level = FALSE, 14 | reverse = FALSE, 15 | label_percentage = 1, 16 | show_version = FALSE, 17 | show_downloads = FALSE, 18 | show_stamp = TRUE, 19 | declutter = FALSE, 20 | ... 21 | ) 22 | 23 | \method{plot_dependencies}{default}( 24 | x, 25 | type = "circular", 26 | same_level = FALSE, 27 | reverse = FALSE, 28 | label_percentage = 1, 29 | show_version = FALSE, 30 | show_downloads = FALSE, 31 | show_stamp = TRUE, 32 | declutter = FALSE, 33 | ... 34 | ) 35 | 36 | \method{plot_dependencies}{character}( 37 | x, 38 | type = "circular", 39 | same_level = FALSE, 40 | reverse = FALSE, 41 | label_percentage = 1, 42 | show_version = FALSE, 43 | show_downloads = FALSE, 44 | show_stamp = TRUE, 45 | declutter = FALSE, 46 | ... 47 | ) 48 | 49 | \method{plot_dependencies}{deepdep}( 50 | x, 51 | type = "circular", 52 | same_level = FALSE, 53 | reverse = FALSE, 54 | label_percentage = 1, 55 | show_version = FALSE, 56 | show_downloads = FALSE, 57 | show_stamp = TRUE, 58 | declutter = FALSE, 59 | ... 60 | ) 61 | } 62 | \arguments{ 63 | \item{x}{A \code{\link{deepdep}} object or a \code{character} package name.} 64 | 65 | \item{type}{A \code{character}. Possible values are \code{circular} and \code{tree}.} 66 | 67 | \item{same_level}{A \code{logical}. If \code{TRUE} links between dependencies on the same 68 | level will be added. By default it's \code{FALSE}.} 69 | 70 | \item{reverse}{A \code{logical}. If \code{TRUE} links between dependencies pointing from 71 | deeper level to more shallow level will be added. By default it's \code{FALSE}.} 72 | 73 | \item{label_percentage}{A \code{numeric} value between \code{0} and \code{1}. A fraction 74 | of labels to be displayed. By default it's \code{1} (all labels displayed).} 75 | 76 | \item{show_version}{A \code{logical}. If \code{TRUE} required version of package will be 77 | displayed below package name. Defaults to \code{FALSE}.} 78 | 79 | \item{show_downloads}{A \code{logical}. If \code{TRUE} total number of downloads of packages 80 | will be displayed below package names. Defaults to \code{FALSE}.} 81 | 82 | \item{show_stamp}{A \code{logical}. If \code{TRUE} (the default) the package version and 83 | plot creation time will be added} 84 | 85 | \item{declutter}{A \code{logical}. If \code{TRUE} then all layers beyond the first one 86 | ignore non-strong dependencies (i.e. "Suggests" and "Enhances"). This visualizes the 87 | so-called "hard costs of weak suggests".} 88 | 89 | \item{...}{Other arguments passed to the \code{deepdep} function.} 90 | } 91 | \value{ 92 | A \code{ggplot2, gg, ggraph, deepdep_plot} class object. 93 | } 94 | \description{ 95 | Visualize dependency data from a \code{deepdep} object using 96 | \code{ggplot2} and \code{ggraph} packages. Several tree-like layouts are available. 97 | } 98 | \examples{ 99 | 100 | \donttest{ 101 | library(deepdep) 102 | 103 | #:# use local packages 104 | plot_dependencies("deepdep", depth = 2, local = TRUE) 105 | 106 | dd <- deepdep("ggplot2") 107 | plot_dependencies(dd, "tree") 108 | 109 | dd2 <- deepdep("ggplot2", depth = 2) 110 | plot_dependencies(dd2, "circular") 111 | 112 | #:# show grand_total download count 113 | plot_dependencies("shiny", show_downloads = TRUE) 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $('.navbar-fixed-top').headroom(); 6 | 7 | $('body').css('padding-top', $('.navbar').height() + 10); 8 | $(window).resize(function(){ 9 | $('body').css('padding-top', $('.navbar').height() + 10); 10 | }); 11 | 12 | $('[data-toggle="tooltip"]').tooltip(); 13 | 14 | var cur_path = paths(location.pathname); 15 | var links = $("#navbar ul li a"); 16 | var max_length = -1; 17 | var pos = -1; 18 | for (var i = 0; i < links.length; i++) { 19 | if (links[i].getAttribute("href") === "#") 20 | continue; 21 | // Ignore external links 22 | if (links[i].host !== location.host) 23 | continue; 24 | 25 | var nav_path = paths(links[i].pathname); 26 | 27 | var length = prefix_length(nav_path, cur_path); 28 | if (length > max_length) { 29 | max_length = length; 30 | pos = i; 31 | } 32 | } 33 | 34 | // Add class to parent
  • , and enclosing
  • if in dropdown 35 | if (pos >= 0) { 36 | var menu_anchor = $(links[pos]); 37 | menu_anchor.parent().addClass("active"); 38 | menu_anchor.closest("li.dropdown").addClass("active"); 39 | } 40 | }); 41 | 42 | function paths(pathname) { 43 | var pieces = pathname.split("/"); 44 | pieces.shift(); // always starts with / 45 | 46 | var end = pieces[pieces.length - 1]; 47 | if (end === "index.html" || end === "") 48 | pieces.pop(); 49 | return(pieces); 50 | } 51 | 52 | // Returns -1 if not found 53 | function prefix_length(needle, haystack) { 54 | if (needle.length > haystack.length) 55 | return(-1); 56 | 57 | // Special case for length-0 haystack, since for loop won't run 58 | if (haystack.length === 0) { 59 | return(needle.length === 0 ? 0 : -1); 60 | } 61 | 62 | for (var i = 0; i < haystack.length; i++) { 63 | if (needle[i] != haystack[i]) 64 | return(i); 65 | } 66 | 67 | return(haystack.length); 68 | } 69 | 70 | /* Clipboard --------------------------*/ 71 | 72 | function changeTooltipMessage(element, msg) { 73 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 74 | element.setAttribute('data-original-title', msg); 75 | $(element).tooltip('show'); 76 | element.setAttribute('data-original-title', tooltipOriginalTitle); 77 | } 78 | 79 | if(ClipboardJS.isSupported()) { 80 | $(document).ready(function() { 81 | var copyButton = ""; 82 | 83 | $(".examples, div.sourceCode").addClass("hasCopyButton"); 84 | 85 | // Insert copy buttons: 86 | $(copyButton).prependTo(".hasCopyButton"); 87 | 88 | // Initialize tooltips: 89 | $('.btn-copy-ex').tooltip({container: 'body'}); 90 | 91 | // Initialize clipboard: 92 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 93 | text: function(trigger) { 94 | return trigger.parentNode.textContent; 95 | } 96 | }); 97 | 98 | clipboardBtnCopies.on('success', function(e) { 99 | changeTooltipMessage(e.trigger, 'Copied!'); 100 | e.clearSelection(); 101 | }); 102 | 103 | clipboardBtnCopies.on('error', function() { 104 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 105 | }); 106 | }); 107 | } 108 | })(window.jQuery || window.$) 109 | -------------------------------------------------------------------------------- /R/deepdep.R: -------------------------------------------------------------------------------- 1 | #' @title Acquire the dependencies of the package on any depth level 2 | #' 3 | #' @description This function is an ultimate wrapper for \code{\link{get_dependencies}}. It inherits all of the arguments and 4 | #' allows to recursively search for the dependencies at the higher level of \code{depth}. 5 | #' 6 | #' @param package A \code{character}. Name of the package that is on CRAN, Bioconductor repository or locally installed. 7 | #' See \code{bioc} and \code{local} arguments. 8 | #' @param depth An \code{integer}. Maximum depth level of the dependency. By default it's \code{1}. 9 | #' @param downloads A \code{logical}. If \code{TRUE} add dependency downloads data. By default it's \code{FALSE}. 10 | #' @param bioc A \code{logical} value. If \code{TRUE} the Bioconductor dependencies data will be taken from the 11 | #' Bioconductor repository. For this option to work properly, \code{BiocManager} package needs to be installed. 12 | #' @param local A \code{logical} value. If \code{TRUE} only data of locally installed packages will be used (without API usage). 13 | #' @param dependency_type A \code{character} vector. Types of the dependencies that should be sought, a subset of 14 | #' \code{c("Imports", "Depends", "LinkingTo", "Suggests", "Enhances")}. Other possibilities are: character string 15 | #' \code{"all"}, a shorthand for the whole vector; character string \code{"most"} for the same vector without \code{"Enhances"}; 16 | #' character string \code{"strong"} (default) for the first three elements of that vector. Works analogously to 17 | #' \code{\link[tools]{package_dependencies}}. 18 | #' 19 | #' @return An object of \code{deepdep} class. 20 | #' 21 | #' @seealso \code{\link{get_dependencies}} 22 | #' 23 | #' @examples 24 | #' 25 | #' \donttest{ 26 | #' library(deepdep) 27 | #' 28 | #' dd_downloads <- deepdep("ggplot2") 29 | #' head(dd_downloads) 30 | #' 31 | #' dd_2 <- deepdep("ggplot2", depth = 2, downloads = TRUE) 32 | #' plot_dependencies(dd_2, "circular") 33 | #' 34 | #' dd_local <- deepdep("deepdep", local = TRUE) 35 | #' plot_dependencies(dd_local) 36 | #' } 37 | #' 38 | #' 39 | #' @export 40 | deepdep <- function(package, depth = 1, downloads = FALSE, bioc = FALSE, local = FALSE, 41 | dependency_type = "strong") { 42 | 43 | check_package_name(package, bioc, local) 44 | 45 | pkg_dep <- get_dependencies(package, downloads, bioc, local, dependency_type) 46 | 47 | # check if there are any dependencies 48 | if (length(pkg_dep$name) > 0) { 49 | ret <- data.frame(origin = package, pkg_dep, origin_level = 0, dest_level = 1) 50 | } else { 51 | ret <- data.frame(origin = character(), pkg_dep, origin_level = numeric(), dest_level = numeric()) 52 | } 53 | 54 | if (depth > 1) { 55 | already_subdeped <- package 56 | to_subdep <- pkg_dep$name 57 | 58 | for (level in 2:depth) { 59 | added <- do.call(rbind, lapply(to_subdep, function(pkg_name) { 60 | pkg_subdep <- get_dependencies(pkg_name, downloads, bioc, local, dependency_type) 61 | if (length(pkg_subdep$name) > 0) { 62 | upper_layer_origin <- ret[match(pkg_subdep$name, ret$origin), "origin_level"] 63 | upper_layer_dest <- ret[match(pkg_subdep$name, ret$name), "dest_level"] 64 | cb <- ifelse(is.na(upper_layer_origin), 65 | ifelse(is.na(upper_layer_dest), level, 66 | upper_layer_dest), 67 | upper_layer_origin) 68 | 69 | data.frame(origin = pkg_name, 70 | pkg_subdep, 71 | origin_level = level - 1, 72 | dest_level = cb) 73 | } else NULL 74 | })) 75 | 76 | already_subdeped <- union(already_subdeped, to_subdep) 77 | to_subdep <- setdiff(added$name, already_subdeped) 78 | ret <- rbind(ret, added) 79 | } 80 | } 81 | 82 | attr(ret, "package_name") <- package 83 | class(ret) <- c("deepdep", "data.frame") 84 | ret 85 | } 86 | 87 | #' @title Print function for an object of \code{deepdep} class 88 | #' 89 | #' @param x An object of \code{deepdep} class. 90 | #' @param ... other 91 | #' 92 | #' 93 | #' @examples 94 | #' \donttest{ 95 | #' library(deepdep) 96 | #' 97 | #' dd <- deepdep("stringr") 98 | #' dd 99 | #' } 100 | #' 101 | #' @rdname print.deepdep 102 | #' @export 103 | print.deepdep <- function(x, ...) { 104 | print.data.frame(x) 105 | } 106 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Visualise and Explore Deep Dependencies of R Packages 3 | 4 | 5 | 6 | [![CRAN 7 | status](https://www.r-pkg.org/badges/version/deepdep)](https://CRAN.R-project.org/package=deepdep) 8 | [![CircleCI build 9 | status](https://circleci.com/gh/DominikRafacz/deepdep.svg?style=svg)](https://circleci.com/gh/DominikRafacz/deepdep) 10 | [![AppVeyor build 11 | status](https://ci.appveyor.com/api/projects/status/github/DominikRafacz/deepdep?branch=master&svg=true)](https://ci.appveyor.com/project/DominikRafacz/deepdep) 12 | [![Codecov test 13 | coverage](https://codecov.io/gh/DominikRafacz/deepdep/branch/master/graph/badge.svg)](https://codecov.io/gh/DominikRafacz/deepdep?branch=master) 14 | [![Lifecycle: 15 | maturing](https://img.shields.io/badge/lifecycle-maturing-blue.svg)](https://www.tidyverse.org/lifecycle/#maturing) 16 | 17 | 18 | 19 | ## Overview 20 | 21 | The `deepdep` package provides tools for exploration of package 22 | dependencies. The main `deepdep()` function allows to acquire deep 23 | dependencies of any package and plot them in an elegant way. It also 24 | adds some popularity measures for the packages e.g. in the form of 25 | download count through the `cranlogs` package. Uses the [CRAN metadata 26 | database](http://crandb.r-pkg.org) and [Bioconductor 27 | metadata](http://bioconductor.org). 28 | 29 | **Exploration tools:** 30 | 31 | - `deepdep()` 32 | - `get_dependencies()` 33 | - `get_downloads()` 34 | - `get_description()` 35 | 36 | **Visualisation tools:** 37 | 38 | - `plot_dependencies()` 39 | - `plot_downloads()` 40 | - `deepdep_shiny()` runs shiny application that helps to produce a nice 41 | **deepdep plot** 42 | 43 | ## Installation 44 | 45 | ``` r 46 | # Install from CRAN: 47 | install.packages("deepdep") 48 | 49 | # Install the development version from GitHub: 50 | devtools::install_github("DominikRafacz/deepdep") 51 | ``` 52 | 53 | ## Examples [**introduction to the deepdep package**](https://dominikrafacz.github.io/deepdep/articles/deepdep-package.html) 54 | 55 | ``` r 56 | library(deepdep) 57 | 58 | dd <- deepdep("ggplot2", depth = 2) 59 | 60 | head(dd) 61 | ``` 62 | 63 | ## origin name version type origin_level dest_level 64 | ## 1 ggplot2 cli Imports 0 1 65 | ## 2 ggplot2 glue Imports 0 1 66 | ## 3 ggplot2 gtable >= 0.1.1 Imports 0 1 67 | ## 4 ggplot2 isoband Imports 0 1 68 | ## 5 ggplot2 lifecycle > 1.0.1 Imports 0 1 69 | ## 6 ggplot2 MASS Imports 0 1 70 | 71 | ``` r 72 | plot_dependencies(dd, "circular") 73 | ``` 74 | 75 | 76 | 77 | ``` r 78 | plot_dependencies("bayes4psy", show_version = TRUE, 79 | dependency_type = c("Depends", "Imports", "Suggests", "LinkingTo")) 80 | ``` 81 | 82 | 83 | 84 | ``` r 85 | dd_xgboost <- deepdep("xgboost", dependency_type = "Imports", downloads = TRUE) 86 | 87 | head(dd_xgboost) 88 | ``` 89 | 90 | ## origin name version type last_day last_week last_month last_quarter last_half grand_total origin_level dest_level 91 | ## 1 xgboost Matrix >= 1.1-0 Imports 5669 78043 317730 1030313 2307023 10546730 0 1 92 | ## 2 xgboost data.table >= 1.9.6 Imports 21766 196875 768217 2494588 5294010 43848884 0 1 93 | ## 3 xgboost jsonlite >= 1.0 Imports 19405 249759 1048356 3110597 7056167 68812509 0 1 94 | 95 | ``` r 96 | plot_downloads(dd_xgboost) 97 | ``` 98 | 99 | 100 | 101 | ``` r 102 | plot_dependencies(dd_xgboost, "tree", show_version = TRUE) 103 | ``` 104 | 105 | 106 | 107 | 110 | -------------------------------------------------------------------------------- /R/plot_downloads.R: -------------------------------------------------------------------------------- 1 | #' @title Plot download count of CRAN packages. 2 | #' 3 | #' @description This function uses \href{https://github.com/r-hub/cranlogs}{\bold{API}} of 4 | #' \href{http://cran-logs.rstudio.com/}{\bold{CRAN Logs}} to scrap the download logs of the packages and 5 | #' then plots the data. It works on objects of class \code{character} (vector), 6 | #' \code{deepdep}, \code{package_dependencies} and \code{package_downloads}. 7 | #' 8 | #' @param x A \code{character} vector. Names of the packages that are on CRAN. 9 | #' @param from A \code{Date} class object. From which date plot the data. By default it's one year back. 10 | #' @param to A \code{Date} class object. To which date plot the data. By default it's now. 11 | #' @param ... Ignored. 12 | #' 13 | #' @return A \code{ggplot2} class object. 14 | #' 15 | #' @examples 16 | #' 17 | #' \donttest{ 18 | #' library(deepdep) 19 | #' 20 | #' plot_downloads("htmltools") 21 | #' 22 | #' dd <- deepdep("ggplot2") 23 | #' plot_downloads(dd) 24 | #' } 25 | #' 26 | #' @importFrom stats time 27 | #' @rdname plot_downloads 28 | #' @export 29 | plot_downloads <- function(x, ...) { 30 | UseMethod("plot_downloads") 31 | } 32 | 33 | #' @rdname plot_downloads 34 | #' @export 35 | plot_downloads.default <- function(x, ...) { 36 | stop("This type of object does not have implemented method for 'plot_downloads'") 37 | } 38 | 39 | #' @rdname plot_downloads 40 | #' @export 41 | plot_downloads.deepdep <- function(x, from = Sys.Date() - 365, to = Sys.Date(), ...) { 42 | 43 | temp <- c(attr(x, "package_name"), unique(as.character(x$name))) 44 | plot_downloads(temp, from, to, ...) 45 | } 46 | 47 | #' @rdname plot_downloads 48 | #' @export 49 | plot_downloads.package_dependencies <- function(x, from = Sys.Date() - 365, to = Sys.Date(), ...) { 50 | 51 | temp <- c(attr(x, "package_name"), unique(as.character(x$name))) 52 | plot_downloads(temp, from, to, ...) 53 | } 54 | 55 | #' @rdname plot_downloads 56 | #' @export 57 | plot_downloads.package_downloads <- function(x, from = Sys.Date() - 365, to = Sys.Date(), ...) { 58 | 59 | temp <- attr(x, "package_name") 60 | plot_downloads(temp, from, to, ...) 61 | } 62 | 63 | #' @rdname plot_downloads 64 | #' @export 65 | plot_downloads.character <- function(x, from = Sys.Date() - 365, to = Sys.Date(), ...) { 66 | # Due to NSE inside of the function, we have to declare "package_name" as NULL to prevent check fail 67 | package_name <- NULL 68 | 69 | if (!require_packages(c("ggplot2", "scales"), 70 | use_case = "plot download statistics")) 71 | stop("Missing necessary packages.") 72 | 73 | # add some x check 74 | 75 | ind <- NULL 76 | 77 | for (i in seq_along(x)) { 78 | tryCatch(check_package_name(x[i], FALSE, FALSE), 79 | error = function(e) { 80 | warning(paste0(x[i], " is not on CRAN.")) 81 | ind <- c(ind, i) 82 | } 83 | ) 84 | } 85 | 86 | if (!is.null(ind)) x <- x[-ind] 87 | 88 | n <- to - from - 1 89 | if (n <= 0) stop("'to' argument is not greater than 'from'") 90 | 91 | data <- data.frame(matrix(NA, ncol = length(x), nrow = n)) 92 | colnames(data) <- x 93 | 94 | for (i in seq_along(x)) { 95 | package <- x[[i]] 96 | 97 | downloads <- cranlogs::cran_downloads(package, from = from, to = to) 98 | 99 | # remove zeros from last two days without data 100 | l <- length(downloads$count) 101 | downloads_count <- downloads$count[-c(l, l - 1)] 102 | 103 | data[package] <- downloads_count 104 | } 105 | 106 | # base::reshape is hard 107 | data_long <- reshape(data, direction = "long", varying = list(seq_along(x)), 108 | times = names(data), timevar = "package_name", 109 | v.names = "downloads", idvar = "time") 110 | 111 | data_long$time <- downloads$date[-c(l, l - 1)] 112 | 113 | ggplot2::ggplot(data_long, ggplot2::aes(time, downloads, color = package_name)) + 114 | ggplot2::geom_smooth(se = FALSE) + 115 | ggplot2::scale_x_date() + 116 | ggplot2::scale_y_continuous(labels = scales::comma) + 117 | ggplot2::xlab("date") + 118 | ggplot2::ylab("daily downloads") + 119 | ggplot2::ggtitle(paste0("Daily downloads for dependencies of the ", x[1], " package")) + 120 | ggplot2::theme_minimal() + 121 | ggplot2::theme(legend.position = "bottom", 122 | legend.title = ggplot2::element_blank()) 123 | } 124 | -------------------------------------------------------------------------------- /R/get_dependencies.R: -------------------------------------------------------------------------------- 1 | #' @title Acquire the dependencies of the package 2 | #' 3 | #' @description This function uses \code{\link{get_description}} and \code{\link{get_downloads}} 4 | #' to acquire the dependencies of the package (with their downloads). 5 | #' 6 | #' @param package A \code{character}. Name of the package that is on CRAN, Bioconductor repository or locally installed. 7 | #' See \code{bioc} and \code{local} arguments. 8 | #' @param downloads A \code{logical}. If \code{TRUE} add package downloads data. By default it's \code{TRUE}. 9 | #' @param bioc A \code{logical} value. If \code{TRUE} the Bioconductor dependencies data will be taken from the 10 | #' Bioconductor repository. For this option to work properly, \code{BiocManager} package needs to be installed. 11 | #' @param local A \code{logical} value. If \code{TRUE} only data of locally installed packages will be used (without API usage). 12 | #' @param dependency_type A \code{character} vector. Types of the dependencies that should be sought, a subset of 13 | #' \code{c("Imports", "Depends", "LinkingTo", "Suggests", "Enhances")}. Other possibilities are: character string 14 | #' \code{"all"}, a shorthand for the whole vector; character string \code{"most"} for the same vector without \code{"Enhances"}; 15 | #' character string \code{"strong"} (default) for the first three elements of that vector. Works analogously to 16 | #' \code{\link[tools]{package_dependencies}}. 17 | #' 18 | #' @return An object of \code{package_dependencies} class. 19 | #' 20 | #' @seealso \code{\link{get_description}} \code{\link{get_downloads}} 21 | #' 22 | #' @examples 23 | #' library(deepdep) 24 | #' 25 | #' \donttest{ 26 | #' dependencies <- get_dependencies("htmltools", downloads = FALSE) 27 | #' dependencies 28 | #' 29 | #' dependencies_local <- get_dependencies("deepdep", downloads = FALSE, local = TRUE) 30 | #' dependencies_local 31 | #' } 32 | #' 33 | #' @export 34 | get_dependencies <- function(package, downloads = TRUE, bioc = FALSE, local = FALSE, 35 | dependency_type = "strong") { 36 | 37 | if (downloads && (local || bioc)) stop("If you use downloads, you cannot use", 38 | " neither bioc nor local") 39 | 40 | dependency_type <- match_dependency_type(dependency_type) 41 | 42 | l_dependency_type <- tolower(dependency_type) 43 | names(dependency_type) <- l_dependency_type 44 | 45 | description <- get_description(package, bioc, local) 46 | 47 | deps <- description[l_dependency_type] 48 | 49 | package_names <- unlist(sapply(deps, names), use.names = FALSE) 50 | package_versions <- unlist(deps, use.names = FALSE) 51 | package_types <- unlist(sapply(names(deps), function(dep_type) 52 | rep(dependency_type[dep_type], length(deps[[dep_type]]))), use.names = FALSE) 53 | 54 | if (!is.null(package_names) && length(package_names) > 0) { 55 | downloads_df <- NULL 56 | remove_base_or_R <- sapply(package_names, 57 | function(pkg_name) is_available(pkg_name, bioc, local)) 58 | 59 | if (downloads) { 60 | downloads_list <- lapply(package_names, get_downloads) 61 | downloads_df <- as.data.frame(do.call(rbind, downloads_list)) 62 | } 63 | 64 | # this works if downloads_df is NULL 65 | ret <- as.data.frame(cbind(name = package_names[remove_base_or_R], 66 | version = package_versions[remove_base_or_R], 67 | type = package_types[remove_base_or_R], 68 | downloads_df), 69 | stringsAsFactors = FALSE) 70 | # deletes downloads_df column if ret is empty 71 | if (is.null(downloads_df)) { 72 | ret$downloads_df <- downloads_df 73 | } 74 | } else return(NULL) 75 | 76 | attr(ret, "package_name") <- package 77 | row.names(ret) <- NULL 78 | class(ret) <- c("package_dependencies", "data.frame") 79 | ret 80 | } 81 | 82 | #' @title Print function for an object of \code{package_dependencies} class 83 | #' 84 | #' @param x An object of \code{package_dependencies} class. 85 | #' @param ... other 86 | #' 87 | #' 88 | #' @examples 89 | #' \donttest{ 90 | #' library(deepdep) 91 | #' 92 | #' get_dependencies("htmltools", downloads = TRUE) 93 | #' } 94 | #' 95 | #' @rdname print.package_dependencies 96 | #' @export 97 | print.package_dependencies <- function(x, ...) { 98 | print.data.frame(x) 99 | } 100 | 101 | #' Match vector of dependency types 102 | #' 103 | #' @inheritParams get_dependencies 104 | #' 105 | #' Based on `tools:::.expand_dependency_type_spec`, according to the suggestion of Dirk Eddelbuettel 106 | #' 107 | #' @noRd 108 | match_dependency_type <- function(dependency_type) { 109 | possible_types <- c("Depends", "Imports", "LinkingTo", "Suggests", "Enhances") 110 | 111 | if (identical(dependency_type, "strong")) possible_types[1:3] 112 | else if (identical(dependency_type, "most")) possible_types[1:4] 113 | else if (identical(dependency_type, "all")) possible_types 114 | else if (!all(dependency_type %in% possible_types) || length(dependency_type) < 1) 115 | stop("'dependency_type' should specify which types of dependencies should be included") 116 | else dependency_type 117 | } 118 | -------------------------------------------------------------------------------- /tests/fixtures/plot-dnl-1.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: http://crandb.r-pkg.org/xgboost 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | Accept: application/json, text/xml, application/xml, */* 10 | response: 11 | status: 12 | status_code: 200 13 | category: Success 14 | reason: OK 15 | message: 'Success: (200) OK' 16 | headers: 17 | date: Mon, 20 Feb 2023 09:45:33 GMT 18 | content-type: application/json 19 | transfer-encoding: chunked 20 | connection: keep-alive 21 | etag: W/"6B5S0RCM1BOCTH4PC7QIGWMNA" 22 | vary: Accept 23 | x-couch-request-id: 687eb25b59 24 | x-couchdb-body-time: '0' 25 | cf-cache-status: DYNAMIC 26 | report-to: '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=gliRyAwmJAucPu9isQ6fo7pH2eCzxeKB7t2z5F81nCUI1l6LUTGTtv%2Bo5hxwhloIjXDxWKlrRhT7kdDMerTnhC0l0XFOdYE0ZLrZAeRkuJdXEValzSnJoV10LXfj2QXHR5eR"}],"group":"cf-nel","max_age":604800}' 27 | nel: '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}' 28 | server: cloudflare 29 | cf-ray: 79c64f5cdbf63570-WAW 30 | content-encoding: gzip 31 | alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400 32 | body: 33 | encoding: '' 34 | file: no 35 | string: '{"Package":"xgboost","Type":"Package","Title":"Extreme Gradient Boosting","Version":"1.7.3.1","Date":"2023-01-06","Authors@R":"c(\u000aperson(\"Tianqi\", 36 | \"Chen\", role = c(\"aut\"),\u000aemail = \"tianqi.tchen@gmail.com\"),\u000aperson(\"Tong\", 37 | \"He\", role = c(\"aut\"),\u000aemail = \"hetong007@gmail.com\"),\u000aperson(\"Michael\", 38 | \"Benesty\", role = c(\"aut\"),\u000aemail = \"michael@benesty.fr\"),\u000aperson(\"Vadim\", 39 | \"Khotilovich\", role = c(\"aut\"),\u000aemail = \"khotilovich@gmail.com\"),\u000aperson(\"Yuan\", 40 | \"Tang\", role = c(\"aut\"),\u000aemail = \"terrytangyuan@gmail.com\",\u000acomment 41 | = c(ORCID = \"0000-0001-5243-233X\")),\u000aperson(\"Hyunsu\", \"Cho\", role 42 | = c(\"aut\"),\u000aemail = \"chohyu01@cs.washington.edu\"),\u000aperson(\"Kailong\", 43 | \"Chen\", role = c(\"aut\")),\u000aperson(\"Rory\", \"Mitchell\", role = c(\"aut\")),\u000aperson(\"Ignacio\", 44 | \"Cano\", role = c(\"aut\")),\u000aperson(\"Tianyi\", \"Zhou\", role = c(\"aut\")),\u000aperson(\"Mu\", 45 | \"Li\", role = c(\"aut\")),\u000aperson(\"Junyuan\", \"Xie\", role = c(\"aut\")),\u000aperson(\"Min\", 46 | \"Lin\", role = c(\"aut\")),\u000aperson(\"Yifeng\", \"Geng\", role = c(\"aut\")),\u000aperson(\"Yutian\", 47 | \"Li\", role = c(\"aut\")),\u000aperson(\"Jiaming\", \"Yuan\", role = c(\"aut\", 48 | \"cre\"),\u000aemail = \"jm.yuan@outlook.com\"),\u000aperson(\"XGBoost contributors\", 49 | role = c(\"cph\"),\u000acomment = \"base XGBoost implementation\")\u000a)","Maintainer":"Jiaming 50 | Yuan ","Description":"Extreme Gradient Boosting, which 51 | is an efficient implementation\u000aof the gradient boosting framework from 52 | Chen & Guestrin (2016) .\u000aThis package is 53 | its R interface. The package includes efficient linear\u000amodel solver and 54 | tree learning algorithms. The package can automatically\u000ado parallel computation 55 | on a single machine which could be more than 10\u000atimes faster than existing 56 | gradient boosting packages. It supports\u000avarious objective functions, 57 | including regression, classification and ranking.\u000aThe package is made 58 | to be extensible, so that users are also allowed to define\u000atheir own 59 | objectives easily.","License":"Apache License (== 2.0) | file LICENSE","URL":"https://github.com/dmlc/xgboost","BugReports":"https://github.com/dmlc/xgboost/issues","NeedsCompilation":"yes","VignetteBuilder":"knitr","Suggests":{"knitr":"*","rmarkdown":"*","ggplot2":">= 60 | 1.0.1","DiagrammeR":">= 0.9.0","Ckmeans.1d.dp":">= 3.3.1","vcd":">= 1.3","testthat":"*","lintr":"*","igraph":">= 61 | 1.0.1","float":"*","crayon":"*","titanic":"*"},"Depends":{"R":">= 3.3.0"},"Imports":{"Matrix":">= 62 | 1.1-0","methods":"*","data.table":">= 1.9.6","jsonlite":">= 1.0"},"RoxygenNote":"7.2.2","SystemRequirements":"GNU 63 | make, C++14","Packaged":"2023-01-14 20:07:58 UTC; jiamingy","Author":"Tianqi 64 | Chen [aut],\u000aTong He [aut],\u000aMichael Benesty [aut],\u000aVadim Khotilovich 65 | [aut],\u000aYuan Tang [aut] (),\u000aHyunsu 66 | Cho [aut],\u000aKailong Chen [aut],\u000aRory Mitchell [aut],\u000aIgnacio 67 | Cano [aut],\u000aTianyi Zhou [aut],\u000aMu Li [aut],\u000aJunyuan Xie [aut],\u000aMin 68 | Lin [aut],\u000aYifeng Geng [aut],\u000aYutian Li [aut],\u000aJiaming Yuan 69 | [aut, cre],\u000aXGBoost contributors [cph] (base XGBoost implementation)","Repository":"CRAN","Date/Publication":"2023-01-14 70 | 21:20:02 UTC","crandb_file_date":"2023-01-14 23:56:43","MD5sum":"b190aba420ee804cc81de029b0f90fd3","date":"2023-01-14T20:20:02+00:00","releases":[]}' 71 | recorded_at: 2023-02-20 09:45:33 GMT 72 | recorded_with: vcr/1.2.0, webmockr/0.8.2 73 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | (function() { 6 | 'use strict'; 7 | 8 | window.Toc = { 9 | helpers: { 10 | // return all matching elements in the set, or their descendants 11 | findOrFilter: function($el, selector) { 12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ 13 | // http://stackoverflow.com/a/12731439/358804 14 | var $descendants = $el.find(selector); 15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); 16 | }, 17 | 18 | generateUniqueIdBase: function(el) { 19 | var text = $(el).text(); 20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); 21 | return anchor || el.tagName.toLowerCase(); 22 | }, 23 | 24 | generateUniqueId: function(el) { 25 | var anchorBase = this.generateUniqueIdBase(el); 26 | for (var i = 0; ; i++) { 27 | var anchor = anchorBase; 28 | if (i > 0) { 29 | // add suffix 30 | anchor += '-' + i; 31 | } 32 | // check if ID already exists 33 | if (!document.getElementById(anchor)) { 34 | return anchor; 35 | } 36 | } 37 | }, 38 | 39 | generateAnchor: function(el) { 40 | if (el.id) { 41 | return el.id; 42 | } else { 43 | var anchor = this.generateUniqueId(el); 44 | el.id = anchor; 45 | return anchor; 46 | } 47 | }, 48 | 49 | createNavList: function() { 50 | return $(''); 51 | }, 52 | 53 | createChildNavList: function($parent) { 54 | var $childList = this.createNavList(); 55 | $parent.append($childList); 56 | return $childList; 57 | }, 58 | 59 | generateNavEl: function(anchor, text) { 60 | var $a = $(''); 61 | $a.attr('href', '#' + anchor); 62 | $a.text(text); 63 | var $li = $('
  • '); 64 | $li.append($a); 65 | return $li; 66 | }, 67 | 68 | generateNavItem: function(headingEl) { 69 | var anchor = this.generateAnchor(headingEl); 70 | var $heading = $(headingEl); 71 | var text = $heading.data('toc-text') || $heading.text(); 72 | return this.generateNavEl(anchor, text); 73 | }, 74 | 75 | // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). 76 | getTopLevel: function($scope) { 77 | for (var i = 1; i <= 6; i++) { 78 | var $headings = this.findOrFilter($scope, 'h' + i); 79 | if ($headings.length > 1) { 80 | return i; 81 | } 82 | } 83 | 84 | return 1; 85 | }, 86 | 87 | // returns the elements for the top level, and the next below it 88 | getHeadings: function($scope, topLevel) { 89 | var topSelector = 'h' + topLevel; 90 | 91 | var secondaryLevel = topLevel + 1; 92 | var secondarySelector = 'h' + secondaryLevel; 93 | 94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector); 95 | }, 96 | 97 | getNavLevel: function(el) { 98 | return parseInt(el.tagName.charAt(1), 10); 99 | }, 100 | 101 | populateNav: function($topContext, topLevel, $headings) { 102 | var $context = $topContext; 103 | var $prevNav; 104 | 105 | var helpers = this; 106 | $headings.each(function(i, el) { 107 | var $newNav = helpers.generateNavItem(el); 108 | var navLevel = helpers.getNavLevel(el); 109 | 110 | // determine the proper $context 111 | if (navLevel === topLevel) { 112 | // use top level 113 | $context = $topContext; 114 | } else if ($prevNav && $context === $topContext) { 115 | // create a new level of the tree and switch to it 116 | $context = helpers.createChildNavList($prevNav); 117 | } // else use the current $context 118 | 119 | $context.append($newNav); 120 | 121 | $prevNav = $newNav; 122 | }); 123 | }, 124 | 125 | parseOps: function(arg) { 126 | var opts; 127 | if (arg.jquery) { 128 | opts = { 129 | $nav: arg 130 | }; 131 | } else { 132 | opts = arg; 133 | } 134 | opts.$scope = opts.$scope || $(document.body); 135 | return opts; 136 | } 137 | }, 138 | 139 | // accepts a jQuery object, or an options object 140 | init: function(opts) { 141 | opts = this.helpers.parseOps(opts); 142 | 143 | // ensure that the data attribute is in place for styling 144 | opts.$nav.attr('data-toggle', 'toc'); 145 | 146 | var $topContext = this.helpers.createChildNavList(opts.$nav); 147 | var topLevel = this.helpers.getTopLevel(opts.$scope); 148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel); 149 | this.helpers.populateNav($topContext, topLevel, $headings); 150 | } 151 | }; 152 | 153 | $(function() { 154 | $('nav[data-toggle="toc"]').each(function(i, el) { 155 | var $nav = $(el); 156 | Toc.init($nav); 157 | }); 158 | }); 159 | })(); 160 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Page not found (404) • deepdep 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
    62 |
    63 | 120 | 121 | 122 | 123 |
    124 | 125 |
    126 |
    127 | 130 | 131 | Content not found. Please use links in the navbar. 132 | 133 |
    134 | 135 | 140 | 141 |
    142 | 143 | 144 | 145 |
    146 | 149 | 150 |
    151 |

    Site built with pkgdown 1.5.1.9000.

    152 |
    153 | 154 |
    155 |
    156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Articles • deepdep 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
    62 |
    63 | 120 | 121 | 122 | 123 |
    124 | 125 |
    126 |
    127 | 130 | 131 |
    132 |

    All vignettes

    133 |

    134 | 135 |
    136 |
    Comparison of deepdep to similar packages
    137 |
    138 |
    deepdep package
    139 |
    140 |
    141 |
    142 |
    143 |
    144 | 145 | 146 |
    147 | 150 | 151 |
    152 |

    Site built with pkgdown 1.5.1.9000.

    153 |
    154 | 155 |
    156 |
    157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Authors • deepdep 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
    62 |
    63 | 120 | 121 | 122 | 123 |
    124 | 125 |
    126 |
    127 | 130 | 131 |
      132 |
    • 133 |

      Dominik Rafacz. Author, maintainer. 134 |

      135 |
    • 136 |
    • 137 |

      Hubert Baniecki. Author. 138 |

      139 |
    • 140 |
    • 141 |

      Szymon Maksymiuk. Author. 142 |

      143 |
    • 144 |
    • 145 |

      Mateusz Bakala. Author. 146 |

      147 |
    • 148 |
    149 | 150 |
    151 | 152 |
    153 | 154 | 155 | 156 |
    157 | 160 | 161 |
    162 |

    Site built with pkgdown 1.5.1.9000.

    163 |
    164 | 165 |
    166 |
    167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /docs/reference/deepdep_shiny.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Run Shiny app — deepdep_shiny • deepdep 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 121 | 122 | 123 | 124 |
    125 | 126 |
    127 |
    128 | 133 | 134 |
    135 |

    This function runs shiny app that helps to produce nice deepdep plot.

    136 |
    137 | 138 |
    deepdep_shiny()
    139 | 140 | 141 | 142 |
    143 | 148 |
    149 | 150 | 151 |
    152 | 155 | 156 |
    157 |

    Site built with pkgdown 1.5.1.9000.

    158 |
    159 | 160 |
    161 |
    162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /vignettes/deepdep-comparison.Rmd.orig: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Comparison of deepdep to similar packages" 3 | author: "Dominik Rafacz" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Comparison of deepdep to similar packages} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | 13 | ```{r, include = FALSE} 14 | knitr::opts_chunk$set( 15 | collapse = TRUE, 16 | comment = "#>", 17 | fig.align = 'center', 18 | fig.width = 7, 19 | fig.height = 5 20 | ) 21 | ``` 22 | 23 | # Comparison to other packages 24 | 25 | There are a few already existing solutions to the problem of visualizing dependencies. In this last section, we will compare `deepdep` to those solutions. 26 | 27 | This solutions are (with links to their GitHub repositories): 28 | 29 | * [datastorm-open/DependenciesGraphs](https://github.com/datastorm-open/DependenciesGraphs) 30 | * [uptake/pkgnet](https://github.com/uptake/pkgnet) 31 | * [andrie/miniCRAN](https://github.com/andrie/miniCRAN) 32 | * [Bioconductor/pkgDepTools](https://github.com/Bioconductor/pkgDepTools) 33 | 34 | # General advantages of deepdep 35 | 36 | First and foremost, our package is the only one that uses `ggplot2` and its enhancements, which is currently the most popular way of visualizing anything in R. You can easily modify plots generated with our package. 37 | 38 | Secondly, we are trying to keep plots clear and tidy. We're rather showing general structure of dependencies, their density and also show, which of the dependencies are the most crucial. 39 | 40 | At last, `deepdep` function is able to show levels of dependencies, which is not true for other packages listed here -- they either show only first-level dependencies or all possible dependencies 41 | 42 | --- 43 | 44 | In the following sections we'll describe why our package is better in some aspects than others, but also features that we're lacking. 45 | 46 | # DependenciesGraphs 47 | 48 | This package allows creating interactive graphs (using `visNetwork`) to visualize dependencies between packages and also between functions in those packages. 49 | 50 | ### Advantages: 51 | 52 | * Interactivity is a great feature. 53 | * Possibility of visualizing dependencies between functions. 54 | * You can add multiple packages instead of one. 55 | * Returned object is kept in a quite popular and easily modifiable format. 56 | * You can run shiny app with the result. 57 | 58 | ### Disadvantages: 59 | 60 | * You have to have installed the package you want to visualize. It is not a great issue, because mostly you visualize your own packages, but if you would like to create some bigger example, including a lot of packages you haven't installed, it may make a problem. 61 | * Graph can get very messy easily and there is no built-in options to prevent it. 62 | * There is no differentiation between levels of dependencies. 63 | * It is available only on GitHub 64 | 65 | ```{r DependenciesGraphs, eval = FALSE} 66 | #> an example from the website on github.io 67 | library(devtools, quietly = TRUE) 68 | install_github("datastorm-open/DependenciesGraphs") 69 | library(DependenciesGraphs, quietly = TRUE) 70 | 71 | # you mus first loaded the target package using library 72 | library(plyr,quietly = TRUE) 73 | 74 | dep <- Pck.load.to.vis("plyr") 75 | plot(dep) 76 | 77 | ``` 78 | 79 | # pkgnet 80 | 81 | Tool for obtaining information on specified package, especially plotting network of package and function dependencies. 82 | 83 | ### Advantages 84 | * It has a fantastic function to automatically generating whole report or vignette on one package. 85 | * Interactive graphs -- again using `visNetwork`. 86 | * It is very convenient and verbose... 87 | 88 | ### Disadvantages 89 | * ...maybe even too much. Sometimes you don't need as much data. 90 | * You cannot do it with small steps -- you get all information at once, if you want only one specific thing, you need to dig through a lot of other informations. 91 | * You have to install the package to get info on it. 92 | 93 | ```{r pkgnet, eval = FALSE} 94 | #> opens a report 95 | library(pkgnet) 96 | result <- CreatePackageReport('ggplot2') 97 | 98 | ``` 99 | # miniCRAN 100 | From README.md on Github: 101 | 102 | > The **miniCRAN** package makes it possible to create an internally consistent repository consisting of selected packages from CRAN-like repositories. The user specifies a set of desired packages, and miniCRAN recursively reads the dependency tree for these packages, then downloads only this subset. 103 | 104 | ### Advantages: 105 | * You can create local repositories and modify them. 106 | * You have wider selection of repositories to choose from. 107 | * Graph in an igraph. 108 | * You can visualize multiple packages at once. 109 | 110 | ### Disadvantages: 111 | * No built-in package support for other plots than base. Which are not very pretty. 112 | 113 | ```{r miniCRAN} 114 | #> an example from official vignette 115 | library(miniCRAN, quietly = TRUE) 116 | 117 | tags <- "chron" 118 | pkgDep(tags, availPkgs = cranJuly2014) 119 | 120 | dg <- makeDepGraph(tags, enhances = TRUE, availPkgs = cranJuly2014) 121 | set.seed(1) 122 | plot(dg, legendPosition = c(-1, 1), vertex.size = 20) 123 | ``` 124 | # pkgDepTools 125 | 126 | Description from official vignette: 127 | 128 | > The **pkgDepTools** package provides tools for computing and 129 | analysing dependency relationships among R packages. With it, you can 130 | build a graph-based representation of the dependencies among all 131 | packages in a list of CRAN-style package repositories. There are 132 | utilities for computing installation order of a given package and, if 133 | the RCurl package is available, estimating the download size required 134 | to install a given package and its dependencies. 135 | 136 | ### Advantages: 137 | * You can pass URL of any repositories, on the contrary to our function, which allows only CRAN, Bioconductor or locally installed packages, but as other repositories are not as commonly used. 138 | 139 | ### Disadvantages: 140 | * There is no possibility of downloading only a part of the packages. Each time you have to wait for the whole repository to be downloaded. 141 | * You cannot choose type of dependencies "Enhances". 142 | * Storage format is `graphNEL` -- not very commonly used and thus not so obvious to modify or adjust. 143 | * This package is pretty outdated. It was created when R was not so popular (and its repositories were quite small) and not modified much since then. 144 | 145 | ```{r pkgDepTools, eval = FALSE} 146 | #> code not evaluated due to very long execution time 147 | library(pkgDepTools) 148 | library(Rgraphviz) 149 | graph <- makeDepGraph("http://cran.fhcrc.org", type="source") 150 | plot(graph) 151 | ``` 152 | -------------------------------------------------------------------------------- /vignettes/deepdep-comparison.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Comparison of deepdep to similar packages" 3 | author: "Dominik Rafacz" 4 | date: "2023-02-20" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Comparison of deepdep to similar packages} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | 13 | 14 | 15 | # Comparison to other packages 16 | 17 | There are a few already existing solutions to the problem of visualizing dependencies. In this last section, we will compare `deepdep` to those solutions. 18 | 19 | This solutions are (with links to their GitHub repositories): 20 | 21 | * [datastorm-open/DependenciesGraphs](https://github.com/datastorm-open/DependenciesGraphs) 22 | * [uptake/pkgnet](https://github.com/uptake/pkgnet) 23 | * [andrie/miniCRAN](https://github.com/andrie/miniCRAN) 24 | * [Bioconductor/pkgDepTools](https://github.com/Bioconductor/pkgDepTools) 25 | 26 | # General advantages of deepdep 27 | 28 | First and foremost, our package is the only one that uses `ggplot2` and its enhancements, which is currently the most popular way of visualizing anything in R. You can easily modify plots generated with our package. 29 | 30 | Secondly, we are trying to keep plots clear and tidy. We're rather showing general structure of dependencies, their density and also show, which of the dependencies are the most crucial. 31 | 32 | At last, `deepdep` function is able to show levels of dependencies, which is not true for other packages listed here -- they either show only first-level dependencies or all possible dependencies 33 | 34 | --- 35 | 36 | In the following sections we'll describe why our package is better in some aspects than others, but also features that we're lacking. 37 | 38 | # DependenciesGraphs 39 | 40 | This package allows creating interactive graphs (using `visNetwork`) to visualize dependencies between packages and also between functions in those packages. 41 | 42 | ### Advantages: 43 | 44 | * Interactivity is a great feature. 45 | * Possibility of visualizing dependencies between functions. 46 | * You can add multiple packages instead of one. 47 | * Returned object is kept in a quite popular and easily modifiable format. 48 | * You can run shiny app with the result. 49 | 50 | ### Disadvantages: 51 | 52 | * You have to have installed the package you want to visualize. It is not a great issue, because mostly you visualize your own packages, but if you would like to create some bigger example, including a lot of packages you haven't installed, it may make a problem. 53 | * Graph can get very messy easily and there is no built-in options to prevent it. 54 | * There is no differentiation between levels of dependencies. 55 | * It is available only on GitHub 56 | 57 | 58 | ```r 59 | #> an example from the website on github.io 60 | library(devtools, quietly = TRUE) 61 | install_github("datastorm-open/DependenciesGraphs") 62 | library(DependenciesGraphs, quietly = TRUE) 63 | 64 | # you mus first loaded the target package using library 65 | library(plyr,quietly = TRUE) 66 | 67 | dep <- Pck.load.to.vis("plyr") 68 | plot(dep) 69 | 70 | ``` 71 | 72 | # pkgnet 73 | 74 | Tool for obtaining information on specified package, especially plotting network of package and function dependencies. 75 | 76 | ### Advantages 77 | * It has a fantastic function to automatically generating whole report or vignette on one package. 78 | * Interactive graphs -- again using `visNetwork`. 79 | * It is very convenient and verbose... 80 | 81 | ### Disadvantages 82 | * ...maybe even too much. Sometimes you don't need as much data. 83 | * You cannot do it with small steps -- you get all information at once, if you want only one specific thing, you need to dig through a lot of other informations. 84 | * You have to install the package to get info on it. 85 | 86 | 87 | ```r 88 | #> opens a report 89 | library(pkgnet) 90 | result <- CreatePackageReport('ggplot2') 91 | 92 | ``` 93 | # miniCRAN 94 | From README.md on Github: 95 | 96 | > The **miniCRAN** package makes it possible to create an internally consistent repository consisting of selected packages from CRAN-like repositories. The user specifies a set of desired packages, and miniCRAN recursively reads the dependency tree for these packages, then downloads only this subset. 97 | 98 | ### Advantages: 99 | * You can create local repositories and modify them. 100 | * You have wider selection of repositories to choose from. 101 | * Graph in an igraph. 102 | * You can visualize multiple packages at once. 103 | 104 | ### Disadvantages: 105 | * No built-in package support for other plots than base. Which are not very pretty. 106 | 107 | 108 | ```r 109 | #> an example from official vignette 110 | library(miniCRAN, quietly = TRUE) 111 | 112 | tags <- "chron" 113 | pkgDep(tags, availPkgs = cranJuly2014) 114 | #> [1] "chron" "RColorBrewer" "dichromat" "munsell" "plyr" "labeling" 115 | #> [7] "colorspace" "Rcpp" "digest" "gtable" "reshape2" "scales" 116 | #> [13] "proto" "MASS" "stringr" "ggplot2" 117 | 118 | dg <- makeDepGraph(tags, enhances = TRUE, availPkgs = cranJuly2014) 119 | set.seed(1) 120 | plot(dg, legendPosition = c(-1, 1), vertex.size = 20) 121 | ``` 122 | 123 | plot of chunk miniCRAN 124 | # pkgDepTools 125 | 126 | Description from official vignette: 127 | 128 | > The **pkgDepTools** package provides tools for computing and 129 | analysing dependency relationships among R packages. With it, you can 130 | build a graph-based representation of the dependencies among all 131 | packages in a list of CRAN-style package repositories. There are 132 | utilities for computing installation order of a given package and, if 133 | the RCurl package is available, estimating the download size required 134 | to install a given package and its dependencies. 135 | 136 | ### Advantages: 137 | * You can pass URL of any repositories, on the contrary to our function, which allows only CRAN, Bioconductor or locally installed packages, but as other repositories are not as commonly used. 138 | 139 | ### Disadvantages: 140 | * There is no possibility of downloading only a part of the packages. Each time you have to wait for the whole repository to be downloaded. 141 | * You cannot choose type of dependencies "Enhances". 142 | * Storage format is `graphNEL` -- not very commonly used and thus not so obvious to modify or adjust. 143 | * This package is pretty outdated. It was created when R was not so popular (and its repositories were quite small) and not modified much since then. 144 | 145 | 146 | ```r 147 | #> code not evaluated due to very long execution time 148 | library(pkgDepTools) 149 | library(Rgraphviz) 150 | graph <- makeDepGraph("http://cran.fhcrc.org", type="source") 151 | plot(graph) 152 | ``` 153 | -------------------------------------------------------------------------------- /docs/news/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Changelog • deepdep 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
    62 |
    63 | 120 | 121 | 122 | 123 |
    124 | 125 |
    126 |
    127 | 131 | 132 |
    133 |

    134 | deepdep 0.2.0 2020-03-06 135 |

    136 |
      137 |
    • CRAN version
    • 138 |
    139 |
    140 |
    141 |

    142 | deepdep 0.1.1 Unreleased 143 |

    144 |
      145 |
    • renamed deps_types argument to dependency_type 146 |
    • 147 |
    • added shiny app that generates deepdep plot
    • 148 |
    149 |
    150 |
    151 |

    152 | deepdep 0.1.0 Unreleased 153 |

    154 | 159 |
    160 |
    161 | 162 | 167 | 168 |
    169 | 170 | 171 |
    172 | 175 | 176 |
    177 |

    Site built with pkgdown 1.5.1.9000.

    178 |
    179 | 180 |
    181 |
    182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /R/get_description.R: -------------------------------------------------------------------------------- 1 | #' @title Scrap the DESCRIPTION file and CRAN metadata of the package 2 | #' 3 | #' @description This function uses api of \href{http://crandb.r-pkg.org}{\bold{CRAN Data Base}} 4 | #' to scrap the DESCRIPTION file and CRAN metadata of the package. It caches the results to speed the computation process. 5 | #' 6 | #' @param package A \code{character}. Name of the package that is on CRAN, Bioconductor repository or locally installed. 7 | #' See \code{bioc} and \code{local} arguments. 8 | #' @param bioc A \code{logical} value. If \code{TRUE} the Bioconductor dependencies data will be taken from the 9 | #' Bioconductor repository. For this option to work properly, \code{BiocManager} package needs to be installed. 10 | #' @param local A \code{logical} value. If \code{TRUE} only data of locally installed packages will be used (without API usage). 11 | #' @param reset_cache A \code{logical} value. If \code{TRUE} the cache will be cleared before obtaining the list of packages. 12 | #' 13 | #' @return An object of \code{package_description} class. 14 | #' 15 | #' 16 | #' @examples 17 | #' library(deepdep) 18 | #' 19 | #' \donttest{ 20 | #' description <- get_description("ggplot2") 21 | #' description 22 | #' 23 | #' description_local <- get_description("deepdep", local = TRUE) 24 | #' description_local 25 | #' } 26 | #' 27 | #' @export 28 | get_description <- function(package, bioc = FALSE, local = FALSE, reset_cache = FALSE) { 29 | if (local && bioc) stop("You cannot use both 'local' and 'bioc' options at once.") 30 | if (reset_cache) reset_cached_files("desc") 31 | if (!is_available(package, bioc, local)) return(NULL) 32 | if (local) return(get_desc_cached(package, "local")) 33 | desc <- NULL 34 | if (bioc) desc <- get_desc_cached(package, "bioc") 35 | if (is.null(desc)) desc <- get_desc_cached(package, "CRAN") 36 | desc 37 | } 38 | 39 | get_desc_cached <- function(package, repo) { 40 | descs <- get_cached_obj("desc", repo) 41 | if (package %in% names(descs)) 42 | return(descs[[package]]) 43 | descs <- switch(repo, 44 | CRAN = append_desc_CRAN(package, descs), 45 | bioc = get_all_desc_bioc(descs), 46 | local = get_desc_local(package, descs)) 47 | attr(descs, "new") <- FALSE 48 | save_cache(descs) 49 | descs[[package]] 50 | } 51 | 52 | append_desc_CRAN <- function(package, descs) { 53 | # get the description 54 | json_as_string <- DB(package) 55 | description <- jsonlite::fromJSON(json_as_string) 56 | 57 | # prettify the description 58 | names(description) <- tolower(names(description)) 59 | 60 | # authors is a vector of "person" class objects (named character) 61 | description$author <- NULL 62 | names(description)[names(description) == "authors@r"] <- "authors" 63 | 64 | # gsub("\n") did not remove all backslashes 65 | # gsub("\\") dit no work 66 | # this apparently works with '\n' in input 67 | # this below was very optimistic 68 | # description$authors <- eval(parse(text = description$authors)) 69 | # this below was very optimistic too 70 | # description$description <- gsub("\n", "", x = description$description, fixed = TRUE) 71 | 72 | # add NA if a version of the dependency is not specified (instead of "*") 73 | for (dep_type in c("depends", "imports", "suggests", "enhances", "linkingto")) { 74 | if (!is.null(description[[dep_type]])) 75 | description[[dep_type]] <- 76 | lapply(description[[dep_type]], function(x) ifelse(x == "*", NA, x)) 77 | } 78 | 79 | # change url to the vector of properl urls 80 | if (!is.null(description$url)) { 81 | description$url <- gsub("\n", "", x = description$url, fixed = TRUE) 82 | description$url <- unlist(strsplit(description$url, ",")) 83 | } 84 | 85 | names(description)[names(description) == "date/publication"] <- "publication_date" 86 | 87 | # what is date? 88 | description$date <- NULL 89 | 90 | # what is releases? 91 | description$releases <- NULL 92 | 93 | ret <- description 94 | 95 | attr(ret, "package_name") <- package 96 | class(ret) <- c("package_description", "list") 97 | descs[[package]] <- ret 98 | descs 99 | } 100 | 101 | #' @importFrom httr GET content 102 | get_all_desc_bioc <- function(descs) { 103 | # if file is not new, it means package is not available via bioc 104 | if (!attr(descs, "new")) descs 105 | 106 | # get all descriptions from bioconductor repository 107 | tmp <- GET("http://bioconductor.org/packages/release/bioc/VIEWS") 108 | tmp <- content(tmp, as = "text", encoding = "UTF-8") 109 | 110 | pkgs <- prepeare_descs(tmp) 111 | # name pakcages 112 | names(pkgs) <- lapply(pkgs, function(pkg) pkg$Package) 113 | 114 | # convert strings of dependencies into vectors 115 | descs <- lapply(pkgs, ajust_desc_file) 116 | 117 | attr(descs, "type") <- "desc" 118 | attr(descs, "repo") <- "bioc" 119 | descs 120 | } 121 | 122 | prepeare_descs <- function(raw_desc) { 123 | mat <- stringi::stri_match_all_regex(raw_desc, "(.*):(?> |\\n)((?>.|\\n )*)\\n")[[1]][, -1] 124 | n <- nrow(mat) 125 | mat[,2] <- stringi::stri_replace_all_regex(mat[, 2], "(\\n)? |\\n", " ") 126 | pkg_begs <- (1:n)[mat[, 1] == "Package"] 127 | pkg_ends <- c((pkg_begs - 1)[-1], n) 128 | 129 | # transform two-column matrix into a list 130 | lapply(1:length(pkg_begs), function(i) { 131 | ret <- as.list(mat[pkg_begs[i]:pkg_ends[i], 2]) 132 | names(ret) <- mat[pkg_begs[i]:pkg_ends[i], 1] 133 | ret 134 | }) -> pkgs 135 | pkgs 136 | } 137 | 138 | ajust_desc_file <- function(pkg) { 139 | nms <- tolower(names(pkg)) 140 | names(pkg) <- nms 141 | for (dep_type in c("depends", "imports", "suggests", "linkingto", "enhances")) { 142 | if (dep_type %in% nms) { 143 | deps <- stringi::stri_match_all_regex( 144 | pkg[[dep_type]], 145 | "(?>\\s*)([^,\\(]+)(?>(?> \\()(\\>\\=[^)]+)(?>\\)))?(?>,|$)")[[1]] 146 | pkg[[dep_type]] <- deps[,3] 147 | names(pkg[[dep_type]]) <- deps[,2] 148 | } 149 | } 150 | attr(pkg, "package_name") <- pkg$Package 151 | class(pkg) <- c("package_description", "list") 152 | pkg 153 | } 154 | 155 | get_desc_local <- function(package, descs) { 156 | # get path to DESCRIPTION file of the package 157 | path <- paste(.libPaths()[1], package, "DESCRIPTION", sep = "/") 158 | # get the description 159 | raw_desc <- readLines(path) 160 | 161 | # prepeare DESCRIPTION so same function as for bioconductor can be used. Packages has to be listed in one line. 162 | merge <- list() 163 | counter <- 0 164 | for (i in 1:length(raw_desc)) { 165 | if (check_if_valid_depend(raw_desc[i])) { 166 | start <- i 167 | } 168 | if (counter > 0) { 169 | if (!grepl(":", raw_desc[i], fixed = TRUE)) { 170 | counter <- counter + 1 171 | if (grepl(":", raw_desc[i + 1], fixed = TRUE)) { 172 | merge[[i]] <- c(start, counter) 173 | counter <- 0 174 | } 175 | } 176 | } 177 | } 178 | 179 | for (vec in merge) { 180 | if(is.null(vec)) next() 181 | raw_desc[vec[1]] <- paste0(raw_desc[vec[1]:(vec[1]+vec[2]-1)], collapse = " ") 182 | raw_desc[(vec[1]+1):(vec[1] + vec[2]-1)] <- "" 183 | } 184 | 185 | raw_desc <- paste0(raw_desc, collapse = "\n") 186 | 187 | # Change raw desc to list 188 | pkg <- prepeare_descs(raw_desc)[[1]] 189 | 190 | ret <- ajust_desc_file(pkg) 191 | 192 | attr(ret, "package_name") <- package 193 | class(ret) <- c("package_description", "list") 194 | descs[[package]] <- ret 195 | descs 196 | } 197 | 198 | check_if_valid_depend <- function(char) { 199 | grepl("Depends", char, fixed = TRUE) | 200 | grepl("Imports", char, fixed = TRUE) | 201 | grepl("Suggests", char, fixed = TRUE) | 202 | grepl("Enhances", char, fixed = TRUE) | 203 | grepl("LinkingTo", char, fixed = TRUE) 204 | } 205 | -------------------------------------------------------------------------------- /docs/reference/get_downloads.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Scrap the download data of the package — get_downloads • deepdep 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 122 | 123 | 124 | 125 |
    126 | 127 |
    128 |
    129 | 134 | 135 |
    136 |

    This function uses API of 137 | CRAN Logs to scrap the download logs of the package.

    138 |
    139 | 140 |
    get_downloads(package)
    141 | 142 |

    Arguments

    143 | 144 | 145 | 146 | 147 | 148 | 149 |
    package

    A character. Name of the package that is on CRAN.

    150 | 151 |

    Value

    152 | 153 |

    An object of package_downloads class.

    154 | 155 |

    Examples

    156 |
    library(deepdep) 157 | 158 | downloads <- get_downloads("ggplot2") 159 | downloads
    #> last_day last_week last_month last_quarter last_half grand_total 160 | #> 1 63519 419446 1586998 4264327 7037518 32633422
    161 | 162 |
    163 |
    164 | 169 |
    170 | 171 | 172 |
    173 | 176 | 177 |
    178 |

    Site built with pkgdown 1.5.1.9000.

    179 |
    180 | 181 |
    182 |
    183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /docs/reference/print.deepdep.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Print function for an object of <code>deepdep</code> class — print.deepdep • deepdep 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 121 | 122 | 123 | 124 |
    125 | 126 |
    127 |
    128 | 133 | 134 |
    135 |

    Print function for an object of deepdep class

    136 |
    137 | 138 |
    # S3 method for deepdep
    139 | print(x, ...)
    140 | 141 |

    Arguments

    142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 |
    x

    An object of deepdep class.

    ...

    other

    153 | 154 | 155 |

    Examples

    156 |
    library(deepdep) 157 | 158 | dd <- deepdep("stringr") 159 | dd
    #> origin name version type origin_level dest_level 160 | #> 1 stringr glue >= 1.2.0 Imports 0 1 161 | #> 2 stringr magrittr <NA> Imports 0 1 162 | #> 3 stringr stringi >= 1.1.7 Imports 0 1
    163 |
    164 |
    165 | 170 |
    171 | 172 | 173 |
    174 | 177 | 178 |
    179 |

    Site built with pkgdown 1.5.1.9000.

    180 |
    181 | 182 |
    183 |
    184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /docs/reference/print.package_downloads.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Print function for an object of <code>package_downloads</code> class — print.package_downloads • deepdep 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 121 | 122 | 123 | 124 |
    125 | 126 |
    127 |
    128 | 133 | 134 |
    135 |

    Print function for an object of package_downloads class

    136 |
    137 | 138 |
    # S3 method for package_downloads
    139 | print(x, ...)
    140 | 141 |

    Arguments

    142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 |
    x

    An object of package_downloads class.

    ...

    other

    153 | 154 | 155 |

    Examples

    156 |
    library(deepdep) 157 | 158 | desc <- get_downloads("stringr") 159 | desc
    #> last_day last_week last_month last_quarter last_half grand_total 160 | #> 1 33470 194352 692084 2138540 4315510 25972950
    161 |
    162 |
    163 | 168 |
    169 | 170 | 171 |
    172 | 175 | 176 |
    177 |

    Site built with pkgdown 1.5.1.9000.

    178 |
    179 | 180 |
    181 |
    182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /docs/reference/print.available_packages.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Print function for an object of <code>available_packages</code> class — print.available_packages • deepdep 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 121 | 122 | 123 | 124 |
    125 | 126 |
    127 |
    128 | 133 | 134 |
    135 |

    Print function for an object of available_packages class

    136 |
    137 | 138 |
    # S3 method for available_packages
    139 | print(x, ...)
    140 | 141 |

    Arguments

    142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 |
    x

    An object of available_packages class.

    ...

    other

    153 | 154 | 155 |

    Examples

    156 |
    library(deepdep) 157 | 158 | av <- get_available_packages() 159 | head(av)
    #> A3 aaSEA ABACUS abbyyR abc abc.data 160 | #> "A3" "aaSEA" "ABACUS" "abbyyR" "abc" "abc.data"
    161 |
    162 |
    163 | 168 |
    169 | 170 | 171 |
    172 | 175 | 176 |
    177 |

    Site built with pkgdown 1.5.1.9000.

    178 |
    179 | 180 |
    181 |
    182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /docs/reference/print.package_dependencies.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Print function for an object of <code>package_dependencies</code> class — print.package_dependencies • deepdep 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 121 | 122 | 123 | 124 |
    125 | 126 |
    127 |
    128 | 133 | 134 |
    135 |

    Print function for an object of package_dependencies class

    136 |
    137 | 138 |
    # S3 method for package_dependencies
    139 | print(x, ...)
    140 | 141 |

    Arguments

    142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 |
    x

    An object of package_dependencies class.

    ...

    other

    153 | 154 | 155 |

    Examples

    156 |
    library(deepdep) 157 | 158 | get_dependencies("htmltools", downloads = TRUE)
    #> name version type last_day last_week last_month last_quarter last_half 159 | #> 1 digest <NA> Imports 42058 247516 886362 2910094 5362694 160 | #> 2 Rcpp <NA> Imports 51692 314447 1172339 3396160 6301969 161 | #> 3 rlang <NA> Imports 65340 390115 1416788 4743357 8723795 162 | #> grand_total 163 | #> 1 27164651 164 | #> 2 36947212 165 | #> 3 29080381
    166 |
    167 |
    168 | 173 |
    174 | 175 | 176 | 186 |
    187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer */ 2 | 3 | /** 4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ 5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css 6 | * 7 | * .Site -> body > .container 8 | * .Site-content -> body > .container .row 9 | * .footer -> footer 10 | * 11 | * Key idea seems to be to ensure that .container and __all its parents__ 12 | * have height set to 100% 13 | * 14 | */ 15 | 16 | html, body { 17 | height: 100%; 18 | } 19 | 20 | body { 21 | position: relative; 22 | } 23 | 24 | body > .container { 25 | display: flex; 26 | height: 100%; 27 | flex-direction: column; 28 | } 29 | 30 | body > .container .row { 31 | flex: 1 0 auto; 32 | } 33 | 34 | footer { 35 | margin-top: 45px; 36 | padding: 35px 0 36px; 37 | border-top: 1px solid #e5e5e5; 38 | color: #666; 39 | display: flex; 40 | flex-shrink: 0; 41 | } 42 | footer p { 43 | margin-bottom: 0; 44 | } 45 | footer div { 46 | flex: 1; 47 | } 48 | footer .pkgdown { 49 | text-align: right; 50 | } 51 | footer p { 52 | margin-bottom: 0; 53 | } 54 | 55 | img.icon { 56 | float: right; 57 | } 58 | 59 | img { 60 | max-width: 100%; 61 | } 62 | 63 | /* Fix bug in bootstrap (only seen in firefox) */ 64 | summary { 65 | display: list-item; 66 | } 67 | 68 | /* Typographic tweaking ---------------------------------*/ 69 | 70 | .contents .page-header { 71 | margin-top: calc(-60px + 1em); 72 | } 73 | 74 | dd { 75 | margin-left: 3em; 76 | } 77 | 78 | /* Section anchors ---------------------------------*/ 79 | 80 | a.anchor { 81 | margin-left: -30px; 82 | display:inline-block; 83 | width: 30px; 84 | height: 30px; 85 | visibility: hidden; 86 | 87 | background-image: url(./link.svg); 88 | background-repeat: no-repeat; 89 | background-size: 20px 20px; 90 | background-position: center center; 91 | } 92 | 93 | .hasAnchor:hover a.anchor { 94 | visibility: visible; 95 | } 96 | 97 | @media (max-width: 767px) { 98 | .hasAnchor:hover a.anchor { 99 | visibility: hidden; 100 | } 101 | } 102 | 103 | 104 | /* Fixes for fixed navbar --------------------------*/ 105 | 106 | .contents h1, .contents h2, .contents h3, .contents h4 { 107 | padding-top: 60px; 108 | margin-top: -40px; 109 | } 110 | 111 | /* Navbar submenu --------------------------*/ 112 | 113 | .dropdown-submenu { 114 | position: relative; 115 | } 116 | 117 | .dropdown-submenu>.dropdown-menu { 118 | top: 0; 119 | left: 100%; 120 | margin-top: -6px; 121 | margin-left: -1px; 122 | border-radius: 0 6px 6px 6px; 123 | } 124 | 125 | .dropdown-submenu:hover>.dropdown-menu { 126 | display: block; 127 | } 128 | 129 | .dropdown-submenu>a:after { 130 | display: block; 131 | content: " "; 132 | float: right; 133 | width: 0; 134 | height: 0; 135 | border-color: transparent; 136 | border-style: solid; 137 | border-width: 5px 0 5px 5px; 138 | border-left-color: #cccccc; 139 | margin-top: 5px; 140 | margin-right: -10px; 141 | } 142 | 143 | .dropdown-submenu:hover>a:after { 144 | border-left-color: #ffffff; 145 | } 146 | 147 | .dropdown-submenu.pull-left { 148 | float: none; 149 | } 150 | 151 | .dropdown-submenu.pull-left>.dropdown-menu { 152 | left: -100%; 153 | margin-left: 10px; 154 | border-radius: 6px 0 6px 6px; 155 | } 156 | 157 | /* Sidebar --------------------------*/ 158 | 159 | #pkgdown-sidebar { 160 | margin-top: 30px; 161 | position: -webkit-sticky; 162 | position: sticky; 163 | top: 70px; 164 | } 165 | 166 | #pkgdown-sidebar h2 { 167 | font-size: 1.5em; 168 | margin-top: 1em; 169 | } 170 | 171 | #pkgdown-sidebar h2:first-child { 172 | margin-top: 0; 173 | } 174 | 175 | #pkgdown-sidebar .list-unstyled li { 176 | margin-bottom: 0.5em; 177 | } 178 | 179 | /* bootstrap-toc tweaks ------------------------------------------------------*/ 180 | 181 | /* All levels of nav */ 182 | 183 | nav[data-toggle='toc'] .nav > li > a { 184 | padding: 4px 20px 4px 6px; 185 | font-size: 1.5rem; 186 | font-weight: 400; 187 | color: inherit; 188 | } 189 | 190 | nav[data-toggle='toc'] .nav > li > a:hover, 191 | nav[data-toggle='toc'] .nav > li > a:focus { 192 | padding-left: 5px; 193 | color: inherit; 194 | border-left: 1px solid #878787; 195 | } 196 | 197 | nav[data-toggle='toc'] .nav > .active > a, 198 | nav[data-toggle='toc'] .nav > .active:hover > a, 199 | nav[data-toggle='toc'] .nav > .active:focus > a { 200 | padding-left: 5px; 201 | font-size: 1.5rem; 202 | font-weight: 400; 203 | color: inherit; 204 | border-left: 2px solid #878787; 205 | } 206 | 207 | /* Nav: second level (shown on .active) */ 208 | 209 | nav[data-toggle='toc'] .nav .nav { 210 | display: none; /* Hide by default, but at >768px, show it */ 211 | padding-bottom: 10px; 212 | } 213 | 214 | nav[data-toggle='toc'] .nav .nav > li > a { 215 | padding-left: 16px; 216 | font-size: 1.35rem; 217 | } 218 | 219 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 220 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 221 | padding-left: 15px; 222 | } 223 | 224 | nav[data-toggle='toc'] .nav .nav > .active > a, 225 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 226 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 227 | padding-left: 15px; 228 | font-weight: 500; 229 | font-size: 1.35rem; 230 | } 231 | 232 | /* orcid ------------------------------------------------------------------- */ 233 | 234 | .orcid { 235 | font-size: 16px; 236 | color: #A6CE39; 237 | /* margins are required by official ORCID trademark and display guidelines */ 238 | margin-left:4px; 239 | margin-right:4px; 240 | vertical-align: middle; 241 | } 242 | 243 | /* Reference index & topics ----------------------------------------------- */ 244 | 245 | .ref-index th {font-weight: normal;} 246 | 247 | .ref-index td {vertical-align: top;} 248 | .ref-index .icon {width: 40px;} 249 | .ref-index .alias {width: 40%;} 250 | .ref-index-icons .alias {width: calc(40% - 40px);} 251 | .ref-index .title {width: 60%;} 252 | 253 | .ref-arguments th {text-align: right; padding-right: 10px;} 254 | .ref-arguments th, .ref-arguments td {vertical-align: top;} 255 | .ref-arguments .name {width: 20%;} 256 | .ref-arguments .desc {width: 80%;} 257 | 258 | /* Nice scrolling for wide elements --------------------------------------- */ 259 | 260 | table { 261 | display: block; 262 | overflow: auto; 263 | } 264 | 265 | /* Syntax highlighting ---------------------------------------------------- */ 266 | 267 | pre { 268 | word-wrap: normal; 269 | word-break: normal; 270 | border: 1px solid #eee; 271 | } 272 | 273 | pre, code { 274 | background-color: #f8f8f8; 275 | color: #333; 276 | } 277 | 278 | pre code { 279 | overflow: auto; 280 | word-wrap: normal; 281 | white-space: pre; 282 | } 283 | 284 | pre .img { 285 | margin: 5px 0; 286 | } 287 | 288 | pre .img img { 289 | background-color: #fff; 290 | display: block; 291 | height: auto; 292 | } 293 | 294 | code a, pre a { 295 | color: #375f84; 296 | } 297 | 298 | a.sourceLine:hover { 299 | text-decoration: none; 300 | } 301 | 302 | .fl {color: #1514b5;} 303 | .fu {color: #000000;} /* function */ 304 | .ch,.st {color: #036a07;} /* string */ 305 | .kw {color: #264D66;} /* keyword */ 306 | .co {color: #888888;} /* comment */ 307 | 308 | .message { color: black; font-weight: bolder;} 309 | .error { color: orange; font-weight: bolder;} 310 | .warning { color: #6A0366; font-weight: bolder;} 311 | 312 | /* Clipboard --------------------------*/ 313 | 314 | .hasCopyButton { 315 | position: relative; 316 | } 317 | 318 | .btn-copy-ex { 319 | position: absolute; 320 | right: 0; 321 | top: 0; 322 | visibility: hidden; 323 | } 324 | 325 | .hasCopyButton:hover button.btn-copy-ex { 326 | visibility: visible; 327 | } 328 | 329 | /* headroom.js ------------------------ */ 330 | 331 | .headroom { 332 | will-change: transform; 333 | transition: transform 200ms linear; 334 | } 335 | .headroom--pinned { 336 | transform: translateY(0%); 337 | } 338 | .headroom--unpinned { 339 | transform: translateY(-100%); 340 | } 341 | 342 | /* mark.js ----------------------------*/ 343 | 344 | mark { 345 | background-color: rgba(255, 255, 51, 0.5); 346 | border-bottom: 2px solid rgba(255, 153, 51, 0.3); 347 | padding: 1px; 348 | } 349 | 350 | /* vertical spacing after htmlwidgets */ 351 | .html-widget { 352 | margin-bottom: 10px; 353 | } 354 | 355 | /* fontawesome ------------------------ */ 356 | 357 | .fab { 358 | font-family: "Font Awesome 5 Brands" !important; 359 | } 360 | 361 | /* don't display links in code chunks when printing */ 362 | /* source: https://stackoverflow.com/a/10781533 */ 363 | @media print { 364 | code a:link:after, code a:visited:after { 365 | content: ""; 366 | } 367 | } 368 | --------------------------------------------------------------------------------