Skip to content

Commit 2257052

Browse files
committed
Merge branch gh-pages of carpentries/styles
2 parents 90446c5 + 243208b commit 2257052

File tree

12 files changed

+179
-99
lines changed

12 files changed

+179
-99
lines changed

.github/workflows/template.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,10 @@ jobs:
137137

138138
- name: Install needed packages
139139
if: steps.check-rmd.outputs.count != 0
140+
working-directory: lesson
140141
run: |
141-
packages = setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages()))
142-
install.packages(packages, repo="https://cran.rstudio.com/")
142+
source('bin/dependencies.R')
143+
install_required_packages(.libPaths()[1])
143144
shell: Rscript {0}
144145

145146
- name: Query dependencies
@@ -149,13 +150,14 @@ jobs:
149150
source('bin/dependencies.R')
150151
deps <- identify_dependencies()
151152
create_description(deps)
153+
use_bioc_repos()
152154
saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
153155
writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version")
154156
shell: Rscript {0}
155157

156-
- name: Cache R packages
158+
- name: Restore Package Cache
157159
if: runner.os != 'Windows' && steps.check-rmd.outputs.count != 0
158-
uses: actions/cache@v1
160+
uses: actions/cache@v2
159161
with:
160162
path: ${{ env.R_LIBS_USER }}
161163
key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }}
@@ -172,7 +174,7 @@ jobs:
172174
run: |
173175
while read -r cmd
174176
do
175-
eval sudo $cmd
177+
eval sudo $cmd || echo "Nothing to update"
176178
done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "20.04"), sep = "\n")')
177179
178180
- run: make site

.github/workflows/website.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ jobs:
5252
with:
5353
r-version: 'release'
5454

55-
- name: Cache R packages
55+
- name: Restore R Cache
5656
if: steps.check-rmd.outputs.count != 0
57-
uses: actions/cache@v1
57+
uses: actions/cache@v2
5858
with:
5959
path: ${{ env.R_LIBS_USER }}
6060
key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }}
@@ -63,8 +63,8 @@ jobs:
6363
- name: Install needed packages
6464
if: steps.check-rmd.outputs.count != 0
6565
run: |
66-
packages = setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages()))
67-
install.packages(packages, repo="https://cran.rstudio.com/")
66+
source('bin/dependencies.R')
67+
install_required_packages()
6868
shell: Rscript {0}
6969

7070
- name: Query dependencies
@@ -73,6 +73,7 @@ jobs:
7373
source('bin/dependencies.R')
7474
deps <- identify_dependencies()
7575
create_description(deps)
76+
use_bioc_repos()
7677
saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
7778
writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version")
7879
shell: Rscript {0}
@@ -83,7 +84,7 @@ jobs:
8384
run: |
8485
while read -r cmd
8586
do
86-
eval sudo $cmd
87+
eval sudo $cmd || echo "Nothing to update"
8788
done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "20.04"), sep = "\n")')
8889
8990
- name: Render the markdown and confirm that the site can be built

_includes/javascript.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<script src="{{ relative_root_path }}/assets/js/jquery.min.js"></script>
55
<script src="{{ relative_root_path }}/assets/js/bootstrap.min.js"></script>
66
<script src="{{ relative_root_path }}/assets/js/lesson.js"></script>
7+
78
<script>
89
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
910
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
@@ -12,6 +13,7 @@
1213
ga('create', 'UA-37305346-2', 'auto');
1314
ga('send', 'pageview');
1415
</script>
16+
1517
{% if page.math %}
1618
<script src="{{ relative_root_path }}/assets/js/katex.min.js"></script>
1719
<script>
@@ -28,3 +30,13 @@
2830
<script src="{{ relative_root_path }}/assets/js/katex-auto-render.min.js" onload="renderMathInElement(document.body, options)"></script>
2931
{% endif %}
3032

33+
{%- comment -%}
34+
AnchorJS: A JavaScript utility for adding deep anchor links
35+
https://github.com/bryanbraun/anchorjs
36+
https://cdn.jsdelivr.net/npm/anchor-js/anchor.min.js
37+
{%- endcomment -%}
38+
39+
<script src="{{ relative_root_path }}/assets/js/anchor.min.js"></script>
40+
<script>
41+
anchors.add();
42+
</script>

assets/css/lesson.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,11 @@ article img {
258258
max-width: 100%;
259259
}
260260

261+
article img.inline {
262+
display: inline-block;
263+
margin: auto;
264+
}
265+
261266
article h2 {
262267
margin: 48px 0 16px;
263268
border-bottom: solid 1px #eaecef;

assets/js/anchor.min.js

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bin/dependencies.R

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
install_required_packages <- function(lib = NULL, repos = getOption("repos", default = c(CRAN = "https://cran.rstudio.com/"))) {
22

33
if (is.null(lib)) {
4-
lib <- .libPaths()
4+
lib <- .libPaths()[[1]]
55
}
66

77
message("lib paths: ", paste(lib, collapse = ", "))
8-
required_pkgs <- c("rprojroot", "desc", "remotes", "renv")
8+
# Note: RMarkdown is needed for renv to detect packages in Rmd documents.
9+
required_pkgs <- c("rprojroot", "desc", "remotes", "renv", "BiocManager", "rmarkdown")
910
installed_pkgs <- rownames(installed.packages(lib.loc = lib))
1011
missing_pkgs <- setdiff(required_pkgs, installed_pkgs)
1112

12-
# The default installation of R will have "@CRAN@" as the default repository, which directs contrib.url() to either
13-
# force the user to choose a mirror if interactive or fail if not. Since we are not interactve, we need to force the
14-
# mirror here.
13+
# The default installation of R will have "@CRAN@" as the default repository,
14+
# which directs contrib.url() to either force the user to choose a mirror if
15+
# interactive or fail if not. Since we are not interactve, we need to force
16+
# the mirror here.
1517
if ("@CRAN@" %in% repos) {
1618
repos <- c(CRAN = "https://cran.rstudio.com/")
1719
}
@@ -29,30 +31,73 @@ find_root <- function() {
2931
root
3032
}
3133

34+
# set the BiocManager repositories and return a function that resets the default
35+
# repositories.
36+
#
37+
# @example
38+
# bioc_repos_example <- function() {
39+
# message("User repos")
40+
# as.data.frame(getOption("repos"))
41+
# reset_repos <- use_bioc_repos()
42+
# on.exit(reset_repos())
43+
# message("Bioc repos")
44+
# as.data.frame(getOption("repos"))
45+
# }
46+
# bioc_repos_example()
47+
# as.data.frame(getOption("repos")
48+
use_bioc_repos <- function() {
49+
repos <- getOption("repos")
50+
suppressMessages(options(repos = BiocManager::repositories()))
51+
function() {
52+
options(repos = repos)
53+
}
54+
}
55+
3256
identify_dependencies <- function() {
3357

3458
root <- find_root()
3559

60+
reset_repos <- use_bioc_repos()
61+
on.exit(reset_repos(), add = TRUE)
62+
eps <- file.path(root, "_episodes_rmd")
63+
bin <- file.path(root, "bin")
64+
3665
required_pkgs <- unique(c(
3766
## Packages for episodes
38-
renv::dependencies(file.path(root, "_episodes_rmd"), progress = FALSE, error = "ignore")$Package,
67+
renv::dependencies(eps, progress = FALSE, error = "ignored")$Package,
3968
## Packages for tools
40-
renv::dependencies(file.path(root, "bin"), progress = FALSE, error = "ignore")$Package
69+
renv::dependencies(bin, progress = FALSE, error = "ignored")$Package
4170
))
4271

4372
required_pkgs
4473
}
4574

4675
create_description <- function(required_pkgs) {
4776
d <- desc::description$new("!new")
48-
lapply(required_pkgs, function(x) d$set_dep(x))
77+
d$set_deps(data.frame(type = "Imports", package = required_pkgs, version = "*"))
4978
d$write("DESCRIPTION")
79+
# We have to write the description twice to get the hidden dependencies
80+
# because renv only considers explicit dependencies.
81+
#
82+
# This is needed because some of the hidden dependencis will require system
83+
# libraries to be configured.
84+
suppressMessages(repo <- BiocManager::repositories())
85+
deps <- remotes::dev_package_deps(dependencies = TRUE, repos = repo)
86+
deps <- deps$package[deps$diff < 0]
87+
if (length(deps)) {
88+
# only create new DESCRIPTION file if there are dependencies to install
89+
d$set_deps(data.frame(type = "Imports", package = deps, version = "*"))
90+
d$write("DESCRIPTION")
91+
}
5092
}
5193

5294
install_dependencies <- function(required_pkgs, ...) {
5395

96+
reset_repos <- use_bioc_repos()
97+
on.exit(reset_repos(), add = TRUE)
98+
5499
create_description(required_pkgs)
55-
on.exit(file.remove("DESCRIPTION"))
100+
on.exit(file.remove("DESCRIPTION"), add = TRUE)
56101
remotes::install_deps(dependencies = TRUE, ...)
57102

58103
if (require("knitr") && packageVersion("knitr") < '1.9.19') {

bin/lesson_check.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
import re
99
from argparse import ArgumentParser
1010

11-
from util import (Reporter, read_markdown, load_yaml, check_unwanted_files,
12-
require)
11+
# This uses the `__all__` list in `util.py` to determine what objects to import
12+
# see https://docs.python.org/3/tutorial/modules.html#importing-from-a-package
13+
from util import *
14+
from reporter import Reporter
1315

1416
__version__ = '0.3'
1517

bin/repo_check.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
import re
1010
from argparse import ArgumentParser
1111

12-
from util import Reporter, require
12+
from util import require
13+
from reporter import Reporter
1314

1415
# Import this way to produce a more useful error message.
1516
try:

bin/reporter.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import sys
2+
3+
class Reporter:
4+
"""Collect and report errors."""
5+
6+
# Marker to show that an expected value hasn't been provided.
7+
# (Can't use 'None' because that might be a legitimate value.)
8+
_DEFAULT_REPORTER = []
9+
10+
def __init__(self):
11+
"""Constructor."""
12+
self.messages = []
13+
14+
def check_field(self, filename, name, values, key, expected=_DEFAULT_REPORTER):
15+
"""Check that a dictionary has an expected value."""
16+
17+
if key not in values:
18+
self.add(filename, '{0} does not contain {1}', name, key)
19+
elif expected is self._DEFAULT_REPORTER:
20+
pass
21+
elif type(expected) in (tuple, set, list):
22+
if values[key] not in expected:
23+
self.add(
24+
filename, '{0} {1} value {2} is not in {3}', name, key, values[key], expected)
25+
elif values[key] != expected:
26+
self.add(filename, '{0} {1} is {2} not {3}',
27+
name, key, values[key], expected)
28+
29+
def check(self, condition, location, fmt, *args):
30+
"""Append error if condition not met."""
31+
32+
if not condition:
33+
self.add(location, fmt, *args)
34+
35+
def add(self, location, fmt, *args):
36+
"""Append error unilaterally."""
37+
38+
self.messages.append((location, fmt.format(*args)))
39+
40+
@staticmethod
41+
def pretty(item):
42+
location, message = item
43+
if isinstance(location, type(None)):
44+
return message
45+
elif isinstance(location, str):
46+
return location + ': ' + message
47+
elif isinstance(location, tuple):
48+
return '{0}:{1}: '.format(*location) + message
49+
50+
print('Unknown item "{0}"'.format(item), file=sys.stderr)
51+
return NotImplemented
52+
53+
@staticmethod
54+
def key(item):
55+
location, message = item
56+
if isinstance(location, type(None)):
57+
return ('', -1, message)
58+
elif isinstance(location, str):
59+
return (location, -1, message)
60+
elif isinstance(location, tuple):
61+
return (location[0], location[1], message)
62+
63+
print('Unknown item "{0}"'.format(item), file=sys.stderr)
64+
return NotImplemented
65+
66+
def report(self, stream=sys.stdout):
67+
"""Report all messages in order."""
68+
69+
if not self.messages:
70+
return
71+
72+
for m in sorted(self.messages, key=self.key):
73+
print(self.pretty(m), file=stream)
74+
75+

bin/test_lesson_check.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import unittest
22

33
import lesson_check
4-
import util
4+
import reporter
55

66

77
class TestFileList(unittest.TestCase):
88
def setUp(self):
9-
self.reporter = util.Reporter() # TODO: refactor reporter class.
9+
self.reporter = reporter.Reporter() # TODO: refactor reporter class.
1010

1111
def test_file_list_has_expected_entries(self):
1212
# For first pass, simply assume that all required files are present

0 commit comments

Comments
 (0)