├── .github └── workflows │ ├── README.md │ ├── pr-close-signal.yaml │ ├── pr-comment.yaml │ ├── pr-post-remove-branch.yaml │ ├── pr-preflight.yaml │ ├── pr-receive.yaml │ ├── sandpaper-main.yaml │ ├── sandpaper-version.txt │ ├── update-cache.yaml │ └── update-workflows.yaml ├── .gitignore ├── .mailmap ├── .update-copyright.conf ├── .zenodo.json ├── AUTHORS ├── CITATION ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── NEWS.md ├── README.md ├── config.yaml ├── files ├── setup-data.md ├── setup-openrefine.md ├── setup-overview.md ├── setup-python.md ├── setup-r.md ├── setup-spreadsheet.md └── setup-sql.md ├── in.md ├── index.md ├── instructors └── instructor-notes.md ├── learners ├── data.md ├── discuss.md ├── reference.md └── setup.Rmd ├── profiles └── learner-profiles.md ├── renv ├── activate.R ├── profile └── profiles │ └── lesson-requirements │ ├── renv.lock │ └── renv │ ├── .gitignore │ └── settings.json ├── setup-python-workshop.Rmd ├── setup-r-workshop.Rmd └── site └── README.md /.github/workflows/README.md: -------------------------------------------------------------------------------- 1 | # Carpentries Workflows 2 | 3 | This directory contains workflows to be used for Lessons using the {sandpaper} 4 | lesson infrastructure. Two of these workflows require R (`sandpaper-main.yaml` 5 | and `pr-receive.yaml`) and the rest are bots to handle pull request management. 6 | 7 | These workflows will likely change as {sandpaper} evolves, so it is important to 8 | keep them up-to-date. To do this in your lesson you can do the following in your 9 | R console: 10 | 11 | ```r 12 | # Install/Update sandpaper 13 | options(repos = c(carpentries = "https://carpentries.r-universe.dev/", 14 | CRAN = "https://cloud.r-project.org")) 15 | install.packages("sandpaper") 16 | 17 | # update the workflows in your lesson 18 | library("sandpaper") 19 | update_github_workflows() 20 | ``` 21 | 22 | Inside this folder, you will find a file called `sandpaper-version.txt`, which 23 | will contain a version number for sandpaper. This will be used in the future to 24 | alert you if a workflow update is needed. 25 | 26 | What follows are the descriptions of the workflow files: 27 | 28 | ## Deployment 29 | 30 | ### 01 Build and Deploy (sandpaper-main.yaml) 31 | 32 | This is the main driver that will only act on the main branch of the repository. 33 | This workflow does the following: 34 | 35 | 1. checks out the lesson 36 | 2. provisions the following resources 37 | - R 38 | - pandoc 39 | - lesson infrastructure (stored in a cache) 40 | - lesson dependencies if needed (stored in a cache) 41 | 3. builds the lesson via `sandpaper:::ci_deploy()` 42 | 43 | #### Caching 44 | 45 | This workflow has two caches; one cache is for the lesson infrastructure and 46 | the other is for the lesson dependencies if the lesson contains rendered 47 | content. These caches are invalidated by new versions of the infrastructure and 48 | the `renv.lock` file, respectively. If there is a problem with the cache, 49 | manual invaliation is necessary. You will need maintain access to the repository 50 | and you can either go to the actions tab and [click on the caches button to find 51 | and invalidate the failing cache](https://github.blog/changelog/2022-10-20-manage-caches-in-your-actions-workflows-from-web-interface/) 52 | or by setting the `CACHE_VERSION` secret to the current date (which will 53 | invalidate all of the caches). 54 | 55 | ## Updates 56 | 57 | ### Setup Information 58 | 59 | These workflows run on a schedule and at the maintainer's request. Because they 60 | create pull requests that update workflows/require the downstream actions to run, 61 | they need a special repository/organization secret token called 62 | `SANDPAPER_WORKFLOW` and it must have the `public_repo` and `workflow` scope. 63 | 64 | This can be an individual user token, OR it can be a trusted bot account. If you 65 | have a repository in one of the official Carpentries accounts, then you do not 66 | need to worry about this token being present because the Carpentries Core Team 67 | will take care of supplying this token. 68 | 69 | If you want to use your personal account: you can go to 70 | 71 | to create a token. Once you have created your token, you should copy it to your 72 | clipboard and then go to your repository's settings > secrets > actions and 73 | create or edit the `SANDPAPER_WORKFLOW` secret, pasting in the generated token. 74 | 75 | If you do not specify your token correctly, the runs will not fail and they will 76 | give you instructions to provide the token for your repository. 77 | 78 | ### 02 Maintain: Update Workflow Files (update-workflow.yaml) 79 | 80 | The {sandpaper} repository was designed to do as much as possible to separate 81 | the tools from the content. For local builds, this is absolutely true, but 82 | there is a minor issue when it comes to workflow files: they must live inside 83 | the repository. 84 | 85 | This workflow ensures that the workflow files are up-to-date. The way it work is 86 | to download the update-workflows.sh script from GitHub and run it. The script 87 | will do the following: 88 | 89 | 1. check the recorded version of sandpaper against the current version on github 90 | 2. update the files if there is a difference in versions 91 | 92 | After the files are updated, if there are any changes, they are pushed to a 93 | branch called `update/workflows` and a pull request is created. Maintainers are 94 | encouraged to review the changes and accept the pull request if the outputs 95 | are okay. 96 | 97 | This update is run weekly or on demand. 98 | 99 | ### 03 Maintain: Update Package Cache (update-cache.yaml) 100 | 101 | For lessons that have generated content, we use {renv} to ensure that the output 102 | is stable. This is controlled by a single lockfile which documents the packages 103 | needed for the lesson and the version numbers. This workflow is skipped in 104 | lessons that do not have generated content. 105 | 106 | Because the lessons need to remain current with the package ecosystem, it's a 107 | good idea to make sure these packages can be updated periodically. The 108 | update cache workflow will do this by checking for updates, applying them in a 109 | branch called `updates/packages` and creating a pull request with _only the 110 | lockfile changed_. 111 | 112 | From here, the markdown documents will be rebuilt and you can inspect what has 113 | changed based on how the packages have updated. 114 | 115 | ## Pull Request and Review Management 116 | 117 | Because our lessons execute code, pull requests are a secruity risk for any 118 | lesson and thus have security measures associted with them. **Do not merge any 119 | pull requests that do not pass checks and do not have bots commented on them.** 120 | 121 | This series of workflows all go together and are described in the following 122 | diagram and the below sections: 123 | 124 | ![Graph representation of a pull request](https://carpentries.github.io/sandpaper/articles/img/pr-flow.dot.svg) 125 | 126 | ### Pre Flight Pull Request Validation (pr-preflight.yaml) 127 | 128 | This workflow runs every time a pull request is created and its purpose is to 129 | validate that the pull request is okay to run. This means the following things: 130 | 131 | 1. The pull request does not contain modified workflow files 132 | 2. If the pull request contains modified workflow files, it does not contain 133 | modified content files (such as a situation where @carpentries-bot will 134 | make an automated pull request) 135 | 3. The pull request does not contain an invalid commit hash (e.g. from a fork 136 | that was made before a lesson was transitioned from styles to use the 137 | workbench). 138 | 139 | Once the checks are finished, a comment is issued to the pull request, which 140 | will allow maintainers to determine if it is safe to run the 141 | "Receive Pull Request" workflow from new contributors. 142 | 143 | ### Receive Pull Request (pr-receive.yaml) 144 | 145 | **Note of caution:** This workflow runs arbitrary code by anyone who creates a 146 | pull request. GitHub has safeguarded the token used in this workflow to have no 147 | priviledges in the repository, but we have taken precautions to protect against 148 | spoofing. 149 | 150 | This workflow is triggered with every push to a pull request. If this workflow 151 | is already running and a new push is sent to the pull request, the workflow 152 | running from the previous push will be cancelled and a new workflow run will be 153 | started. 154 | 155 | The first step of this workflow is to check if it is valid (e.g. that no 156 | workflow files have been modified). If there are workflow files that have been 157 | modified, a comment is made that indicates that the workflow is not run. If 158 | both a workflow file and lesson content is modified, an error will occurr. 159 | 160 | The second step (if valid) is to build the generated content from the pull 161 | request. This builds the content and uploads three artifacts: 162 | 163 | 1. The pull request number (pr) 164 | 2. A summary of changes after the rendering process (diff) 165 | 3. The rendered files (build) 166 | 167 | Because this workflow builds generated content, it follows the same general 168 | process as the `sandpaper-main` workflow with the same caching mechanisms. 169 | 170 | The artifacts produced are used by the next workflow. 171 | 172 | ### Comment on Pull Request (pr-comment.yaml) 173 | 174 | This workflow is triggered if the `pr-receive.yaml` workflow is successful. 175 | The steps in this workflow are: 176 | 177 | 1. Test if the workflow is valid and comment the validity of the workflow to the 178 | pull request. 179 | 2. If it is valid: create an orphan branch with two commits: the current state 180 | of the repository and the proposed changes. 181 | 3. If it is valid: update the pull request comment with the summary of changes 182 | 183 | Importantly: if the pull request is invalid, the branch is not created so any 184 | malicious code is not published. 185 | 186 | From here, the maintainer can request changes from the author and eventually 187 | either merge or reject the PR. When this happens, if the PR was valid, the 188 | preview branch needs to be deleted. 189 | 190 | ### Send Close PR Signal (pr-close-signal.yaml) 191 | 192 | Triggered any time a pull request is closed. This emits an artifact that is the 193 | pull request number for the next action 194 | 195 | ### Remove Pull Request Branch (pr-post-remove-branch.yaml) 196 | 197 | Tiggered by `pr-close-signal.yaml`. This removes the temporary branch associated with 198 | the pull request (if it was created). 199 | -------------------------------------------------------------------------------- /.github/workflows/pr-close-signal.yaml: -------------------------------------------------------------------------------- 1 | name: "Bot: Send Close Pull Request Signal" 2 | 3 | on: 4 | pull_request: 5 | types: 6 | [closed] 7 | 8 | jobs: 9 | send-close-signal: 10 | name: "Send closing signal" 11 | runs-on: ubuntu-22.04 12 | if: ${{ github.event.action == 'closed' }} 13 | steps: 14 | - name: "Create PRtifact" 15 | run: | 16 | mkdir -p ./pr 17 | printf ${{ github.event.number }} > ./pr/NUM 18 | - name: Upload Diff 19 | uses: actions/upload-artifact@v4 20 | with: 21 | name: pr 22 | path: ./pr 23 | -------------------------------------------------------------------------------- /.github/workflows/pr-comment.yaml: -------------------------------------------------------------------------------- 1 | name: "Bot: Comment on the Pull Request" 2 | 3 | # read-write repo token 4 | # access to secrets 5 | on: 6 | workflow_run: 7 | workflows: ["Receive Pull Request"] 8 | types: 9 | - completed 10 | 11 | concurrency: 12 | group: pr-${{ github.event.workflow_run.pull_requests[0].number }} 13 | cancel-in-progress: true 14 | 15 | 16 | jobs: 17 | # Pull requests are valid if: 18 | # - they match the sha of the workflow run head commit 19 | # - they are open 20 | # - no .github files were committed 21 | test-pr: 22 | name: "Test if pull request is valid" 23 | runs-on: ubuntu-22.04 24 | if: > 25 | github.event.workflow_run.event == 'pull_request' && 26 | github.event.workflow_run.conclusion == 'success' 27 | outputs: 28 | is_valid: ${{ steps.check-pr.outputs.VALID }} 29 | payload: ${{ steps.check-pr.outputs.payload }} 30 | number: ${{ steps.get-pr.outputs.NUM }} 31 | msg: ${{ steps.check-pr.outputs.MSG }} 32 | steps: 33 | - name: 'Download PR artifact' 34 | id: dl 35 | uses: carpentries/actions/download-workflow-artifact@main 36 | with: 37 | run: ${{ github.event.workflow_run.id }} 38 | name: 'pr' 39 | 40 | - name: "Get PR Number" 41 | if: ${{ steps.dl.outputs.success == 'true' }} 42 | id: get-pr 43 | run: | 44 | unzip pr.zip 45 | echo "NUM=$(<./NR)" >> $GITHUB_OUTPUT 46 | 47 | - name: "Fail if PR number was not present" 48 | id: bad-pr 49 | if: ${{ steps.dl.outputs.success != 'true' }} 50 | run: | 51 | echo '::error::A pull request number was not recorded. The pull request that triggered this workflow is likely malicious.' 52 | exit 1 53 | - name: "Get Invalid Hashes File" 54 | id: hash 55 | run: | 56 | echo "json<> $GITHUB_OUTPUT 59 | - name: "Check PR" 60 | id: check-pr 61 | if: ${{ steps.dl.outputs.success == 'true' }} 62 | uses: carpentries/actions/check-valid-pr@main 63 | with: 64 | pr: ${{ steps.get-pr.outputs.NUM }} 65 | sha: ${{ github.event.workflow_run.head_sha }} 66 | headroom: 3 # if it's within the last three commits, we can keep going, because it's likely rapid-fire 67 | invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} 68 | fail_on_error: true 69 | 70 | # Create an orphan branch on this repository with two commits 71 | # - the current HEAD of the md-outputs branch 72 | # - the output from running the current HEAD of the pull request through 73 | # the md generator 74 | create-branch: 75 | name: "Create Git Branch" 76 | needs: test-pr 77 | runs-on: ubuntu-22.04 78 | if: ${{ needs.test-pr.outputs.is_valid == 'true' }} 79 | env: 80 | NR: ${{ needs.test-pr.outputs.number }} 81 | permissions: 82 | contents: write 83 | steps: 84 | - name: 'Checkout md outputs' 85 | uses: actions/checkout@v4 86 | with: 87 | ref: md-outputs 88 | path: built 89 | fetch-depth: 1 90 | 91 | - name: 'Download built markdown' 92 | id: dl 93 | uses: carpentries/actions/download-workflow-artifact@main 94 | with: 95 | run: ${{ github.event.workflow_run.id }} 96 | name: 'built' 97 | 98 | - if: ${{ steps.dl.outputs.success == 'true' }} 99 | run: unzip built.zip 100 | 101 | - name: "Create orphan and push" 102 | if: ${{ steps.dl.outputs.success == 'true' }} 103 | run: | 104 | cd built/ 105 | git config --local user.email "actions@github.com" 106 | git config --local user.name "GitHub Actions" 107 | CURR_HEAD=$(git rev-parse HEAD) 108 | git checkout --orphan md-outputs-PR-${NR} 109 | git add -A 110 | git commit -m "source commit: ${CURR_HEAD}" 111 | ls -A | grep -v '^.git$' | xargs -I _ rm -r '_' 112 | cd .. 113 | unzip -o -d built built.zip 114 | cd built 115 | git add -A 116 | git commit --allow-empty -m "differences for PR #${NR}" 117 | git push -u --force --set-upstream origin md-outputs-PR-${NR} 118 | 119 | # Comment on the Pull Request with a link to the branch and the diff 120 | comment-pr: 121 | name: "Comment on Pull Request" 122 | needs: [test-pr, create-branch] 123 | runs-on: ubuntu-22.04 124 | if: ${{ needs.test-pr.outputs.is_valid == 'true' }} 125 | env: 126 | NR: ${{ needs.test-pr.outputs.number }} 127 | permissions: 128 | pull-requests: write 129 | steps: 130 | - name: 'Download comment artifact' 131 | id: dl 132 | uses: carpentries/actions/download-workflow-artifact@main 133 | with: 134 | run: ${{ github.event.workflow_run.id }} 135 | name: 'diff' 136 | 137 | - if: ${{ steps.dl.outputs.success == 'true' }} 138 | run: unzip ${{ github.workspace }}/diff.zip 139 | 140 | - name: "Comment on PR" 141 | id: comment-diff 142 | if: ${{ steps.dl.outputs.success == 'true' }} 143 | uses: carpentries/actions/comment-diff@main 144 | with: 145 | pr: ${{ env.NR }} 146 | path: ${{ github.workspace }}/diff.md 147 | 148 | # Comment if the PR is open and matches the SHA, but the workflow files have 149 | # changed 150 | comment-changed-workflow: 151 | name: "Comment if workflow files have changed" 152 | needs: test-pr 153 | runs-on: ubuntu-22.04 154 | if: ${{ always() && needs.test-pr.outputs.is_valid == 'false' }} 155 | env: 156 | NR: ${{ github.event.workflow_run.pull_requests[0].number }} 157 | body: ${{ needs.test-pr.outputs.msg }} 158 | permissions: 159 | pull-requests: write 160 | steps: 161 | - name: 'Check for spoofing' 162 | id: dl 163 | uses: carpentries/actions/download-workflow-artifact@main 164 | with: 165 | run: ${{ github.event.workflow_run.id }} 166 | name: 'built' 167 | 168 | - name: 'Alert if spoofed' 169 | id: spoof 170 | if: ${{ steps.dl.outputs.success == 'true' }} 171 | run: | 172 | echo 'body<> $GITHUB_ENV 173 | echo '' >> $GITHUB_ENV 174 | echo '## :x: DANGER :x:' >> $GITHUB_ENV 175 | echo 'This pull request has modified workflows that created output. Close this now.' >> $GITHUB_ENV 176 | echo '' >> $GITHUB_ENV 177 | echo 'EOF' >> $GITHUB_ENV 178 | 179 | - name: "Comment on PR" 180 | id: comment-diff 181 | uses: carpentries/actions/comment-diff@main 182 | with: 183 | pr: ${{ env.NR }} 184 | body: ${{ env.body }} 185 | -------------------------------------------------------------------------------- /.github/workflows/pr-post-remove-branch.yaml: -------------------------------------------------------------------------------- 1 | name: "Bot: Remove Temporary PR Branch" 2 | 3 | on: 4 | workflow_run: 5 | workflows: ["Bot: Send Close Pull Request Signal"] 6 | types: 7 | - completed 8 | 9 | jobs: 10 | delete: 11 | name: "Delete branch from Pull Request" 12 | runs-on: ubuntu-22.04 13 | if: > 14 | github.event.workflow_run.event == 'pull_request' && 15 | github.event.workflow_run.conclusion == 'success' 16 | permissions: 17 | contents: write 18 | steps: 19 | - name: 'Download artifact' 20 | uses: carpentries/actions/download-workflow-artifact@main 21 | with: 22 | run: ${{ github.event.workflow_run.id }} 23 | name: pr 24 | - name: "Get PR Number" 25 | id: get-pr 26 | run: | 27 | unzip pr.zip 28 | echo "NUM=$(<./NUM)" >> $GITHUB_OUTPUT 29 | - name: 'Remove branch' 30 | uses: carpentries/actions/remove-branch@main 31 | with: 32 | pr: ${{ steps.get-pr.outputs.NUM }} 33 | -------------------------------------------------------------------------------- /.github/workflows/pr-preflight.yaml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Preflight Check" 2 | 3 | on: 4 | pull_request_target: 5 | branches: 6 | ["main"] 7 | types: 8 | ["opened", "synchronize", "reopened"] 9 | 10 | jobs: 11 | test-pr: 12 | name: "Test if pull request is valid" 13 | if: ${{ github.event.action != 'closed' }} 14 | runs-on: ubuntu-22.04 15 | outputs: 16 | is_valid: ${{ steps.check-pr.outputs.VALID }} 17 | permissions: 18 | pull-requests: write 19 | steps: 20 | - name: "Get Invalid Hashes File" 21 | id: hash 22 | run: | 23 | echo "json<> $GITHUB_OUTPUT 26 | - name: "Check PR" 27 | id: check-pr 28 | uses: carpentries/actions/check-valid-pr@main 29 | with: 30 | pr: ${{ github.event.number }} 31 | invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} 32 | fail_on_error: true 33 | - name: "Comment result of validation" 34 | id: comment-diff 35 | if: ${{ always() }} 36 | uses: carpentries/actions/comment-diff@main 37 | with: 38 | pr: ${{ github.event.number }} 39 | body: ${{ steps.check-pr.outputs.MSG }} 40 | -------------------------------------------------------------------------------- /.github/workflows/pr-receive.yaml: -------------------------------------------------------------------------------- 1 | name: "Receive Pull Request" 2 | 3 | on: 4 | pull_request: 5 | types: 6 | [opened, synchronize, reopened] 7 | 8 | concurrency: 9 | group: ${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | test-pr: 14 | name: "Record PR number" 15 | if: ${{ github.event.action != 'closed' }} 16 | runs-on: ubuntu-22.04 17 | outputs: 18 | is_valid: ${{ steps.check-pr.outputs.VALID }} 19 | steps: 20 | - name: "Record PR number" 21 | id: record 22 | if: ${{ always() }} 23 | run: | 24 | echo ${{ github.event.number }} > ${{ github.workspace }}/NR # 2022-03-02: artifact name fixed to be NR 25 | - name: "Upload PR number" 26 | id: upload 27 | if: ${{ always() }} 28 | uses: actions/upload-artifact@v4 29 | with: 30 | name: pr 31 | path: ${{ github.workspace }}/NR 32 | - name: "Get Invalid Hashes File" 33 | id: hash 34 | run: | 35 | echo "json<> $GITHUB_OUTPUT 38 | - name: "echo output" 39 | run: | 40 | echo "${{ steps.hash.outputs.json }}" 41 | - name: "Check PR" 42 | id: check-pr 43 | uses: carpentries/actions/check-valid-pr@main 44 | with: 45 | pr: ${{ github.event.number }} 46 | invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} 47 | 48 | build-md-source: 49 | name: "Build markdown source files if valid" 50 | needs: test-pr 51 | runs-on: ubuntu-22.04 52 | if: ${{ needs.test-pr.outputs.is_valid == 'true' }} 53 | env: 54 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 55 | RENV_PATHS_ROOT: ~/.local/share/renv/ 56 | CHIVE: ${{ github.workspace }}/site/chive 57 | PR: ${{ github.workspace }}/site/pr 58 | MD: ${{ github.workspace }}/site/built 59 | steps: 60 | - name: "Check Out Main Branch" 61 | uses: actions/checkout@v4 62 | 63 | - name: "Check Out Staging Branch" 64 | uses: actions/checkout@v4 65 | with: 66 | ref: md-outputs 67 | path: ${{ env.MD }} 68 | 69 | - name: "Set up R" 70 | uses: r-lib/actions/setup-r@v2 71 | with: 72 | use-public-rspm: true 73 | install-r: false 74 | 75 | - name: "Set up Pandoc" 76 | uses: r-lib/actions/setup-pandoc@v2 77 | 78 | - name: "Setup Lesson Engine" 79 | uses: carpentries/actions/setup-sandpaper@main 80 | with: 81 | cache-version: ${{ secrets.CACHE_VERSION }} 82 | 83 | - name: "Setup Package Cache" 84 | uses: carpentries/actions/setup-lesson-deps@main 85 | with: 86 | cache-version: ${{ secrets.CACHE_VERSION }} 87 | 88 | - name: "Validate and Build Markdown" 89 | id: build-site 90 | run: | 91 | sandpaper::package_cache_trigger(TRUE) 92 | sandpaper::validate_lesson(path = '${{ github.workspace }}') 93 | sandpaper:::build_markdown(path = '${{ github.workspace }}', quiet = FALSE) 94 | shell: Rscript {0} 95 | 96 | - name: "Generate Artifacts" 97 | id: generate-artifacts 98 | run: | 99 | sandpaper:::ci_bundle_pr_artifacts( 100 | repo = '${{ github.repository }}', 101 | pr_number = '${{ github.event.number }}', 102 | path_md = '${{ env.MD }}', 103 | path_pr = '${{ env.PR }}', 104 | path_archive = '${{ env.CHIVE }}', 105 | branch = 'md-outputs' 106 | ) 107 | shell: Rscript {0} 108 | 109 | - name: "Upload PR" 110 | uses: actions/upload-artifact@v4 111 | with: 112 | name: pr 113 | path: ${{ env.PR }} 114 | overwrite: true 115 | 116 | - name: "Upload Diff" 117 | uses: actions/upload-artifact@v4 118 | with: 119 | name: diff 120 | path: ${{ env.CHIVE }} 121 | retention-days: 1 122 | 123 | - name: "Upload Build" 124 | uses: actions/upload-artifact@v4 125 | with: 126 | name: built 127 | path: ${{ env.MD }} 128 | retention-days: 1 129 | 130 | - name: "Teardown" 131 | run: sandpaper::reset_site() 132 | shell: Rscript {0} 133 | -------------------------------------------------------------------------------- /.github/workflows/sandpaper-main.yaml: -------------------------------------------------------------------------------- 1 | name: "01 Build and Deploy Site" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | schedule: 9 | - cron: '0 0 * * 2' 10 | workflow_dispatch: 11 | inputs: 12 | name: 13 | description: 'Who triggered this build?' 14 | required: true 15 | default: 'Maintainer (via GitHub)' 16 | reset: 17 | description: 'Reset cached markdown files' 18 | required: false 19 | default: false 20 | type: boolean 21 | jobs: 22 | full-build: 23 | name: "Build Full Site" 24 | 25 | # 2024-10-01: ubuntu-latest is now 24.04 and R is not installed by default in the runner image 26 | # pin to 22.04 for now 27 | runs-on: ubuntu-22.04 28 | permissions: 29 | checks: write 30 | contents: write 31 | pages: write 32 | env: 33 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 34 | RENV_PATHS_ROOT: ~/.local/share/renv/ 35 | steps: 36 | 37 | - name: "Checkout Lesson" 38 | uses: actions/checkout@v4 39 | 40 | - name: "Set up R" 41 | uses: r-lib/actions/setup-r@v2 42 | with: 43 | use-public-rspm: true 44 | install-r: false 45 | 46 | - name: "Set up Pandoc" 47 | uses: r-lib/actions/setup-pandoc@v2 48 | 49 | - name: "Setup Lesson Engine" 50 | uses: carpentries/actions/setup-sandpaper@main 51 | with: 52 | cache-version: ${{ secrets.CACHE_VERSION }} 53 | 54 | - name: "Setup Package Cache" 55 | uses: carpentries/actions/setup-lesson-deps@main 56 | with: 57 | cache-version: ${{ secrets.CACHE_VERSION }} 58 | 59 | - name: "Deploy Site" 60 | run: | 61 | reset <- "${{ github.event.inputs.reset }}" == "true" 62 | sandpaper::package_cache_trigger(TRUE) 63 | sandpaper:::ci_deploy(reset = reset) 64 | shell: Rscript {0} 65 | -------------------------------------------------------------------------------- /.github/workflows/sandpaper-version.txt: -------------------------------------------------------------------------------- 1 | 0.16.12 2 | -------------------------------------------------------------------------------- /.github/workflows/update-cache.yaml: -------------------------------------------------------------------------------- 1 | name: "03 Maintain: Update Package Cache" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | name: 7 | description: 'Who triggered this build (enter github username to tag yourself)?' 8 | required: true 9 | default: 'monthly run' 10 | schedule: 11 | # Run every tuesday 12 | - cron: '0 0 * * 2' 13 | 14 | jobs: 15 | preflight: 16 | name: "Preflight Check" 17 | runs-on: ubuntu-22.04 18 | outputs: 19 | ok: ${{ steps.check.outputs.ok }} 20 | steps: 21 | - id: check 22 | run: | 23 | if [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then 24 | echo "ok=true" >> $GITHUB_OUTPUT 25 | echo "Running on request" 26 | # using single brackets here to avoid 08 being interpreted as octal 27 | # https://github.com/carpentries/sandpaper/issues/250 28 | elif [ `date +%d` -le 7 ]; then 29 | # If the Tuesday lands in the first week of the month, run it 30 | echo "ok=true" >> $GITHUB_OUTPUT 31 | echo "Running on schedule" 32 | else 33 | echo "ok=false" >> $GITHUB_OUTPUT 34 | echo "Not Running Today" 35 | fi 36 | 37 | check_renv: 38 | name: "Check if We Need {renv}" 39 | runs-on: ubuntu-22.04 40 | needs: preflight 41 | if: ${{ needs.preflight.outputs.ok == 'true'}} 42 | outputs: 43 | needed: ${{ steps.renv.outputs.exists }} 44 | steps: 45 | - name: "Checkout Lesson" 46 | uses: actions/checkout@v4 47 | - id: renv 48 | run: | 49 | if [[ -d renv ]]; then 50 | echo "exists=true" >> $GITHUB_OUTPUT 51 | fi 52 | 53 | check_token: 54 | name: "Check SANDPAPER_WORKFLOW token" 55 | runs-on: ubuntu-22.04 56 | needs: check_renv 57 | if: ${{ needs.check_renv.outputs.needed == 'true' }} 58 | outputs: 59 | workflow: ${{ steps.validate.outputs.wf }} 60 | repo: ${{ steps.validate.outputs.repo }} 61 | steps: 62 | - name: "validate token" 63 | id: validate 64 | uses: carpentries/actions/check-valid-credentials@main 65 | with: 66 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 67 | 68 | update_cache: 69 | name: "Update Package Cache" 70 | needs: check_token 71 | if: ${{ needs.check_token.outputs.repo== 'true' }} 72 | runs-on: ubuntu-22.04 73 | env: 74 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 75 | RENV_PATHS_ROOT: ~/.local/share/renv/ 76 | steps: 77 | 78 | - name: "Checkout Lesson" 79 | uses: actions/checkout@v4 80 | 81 | - name: "Set up R" 82 | uses: r-lib/actions/setup-r@v2 83 | with: 84 | use-public-rspm: true 85 | install-r: false 86 | 87 | - name: "Update {renv} deps and determine if a PR is needed" 88 | id: update 89 | uses: carpentries/actions/update-lockfile@main 90 | with: 91 | cache-version: ${{ secrets.CACHE_VERSION }} 92 | 93 | - name: Create Pull Request 94 | id: cpr 95 | if: ${{ steps.update.outputs.n > 0 }} 96 | uses: carpentries/create-pull-request@main 97 | with: 98 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 99 | delete-branch: true 100 | branch: "update/packages" 101 | commit-message: "[actions] update ${{ steps.update.outputs.n }} packages" 102 | title: "Update ${{ steps.update.outputs.n }} packages" 103 | body: | 104 | :robot: This is an automated build 105 | 106 | This will update ${{ steps.update.outputs.n }} packages in your lesson with the following versions: 107 | 108 | ``` 109 | ${{ steps.update.outputs.report }} 110 | ``` 111 | 112 | :stopwatch: In a few minutes, a comment will appear that will show you how the output has changed based on these updates. 113 | 114 | If you want to inspect these changes locally, you can use the following code to check out a new branch: 115 | 116 | ```bash 117 | git fetch origin update/packages 118 | git checkout update/packages 119 | ``` 120 | 121 | - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} 122 | 123 | [1]: https://github.com/carpentries/create-pull-request/tree/main 124 | labels: "type: package cache" 125 | draft: false 126 | -------------------------------------------------------------------------------- /.github/workflows/update-workflows.yaml: -------------------------------------------------------------------------------- 1 | name: "02 Maintain: Update Workflow Files" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | name: 7 | description: 'Who triggered this build (enter github username to tag yourself)?' 8 | required: true 9 | default: 'weekly run' 10 | clean: 11 | description: 'Workflow files/file extensions to clean (no wildcards, enter "" for none)' 12 | required: false 13 | default: '.yaml' 14 | schedule: 15 | # Run every Tuesday 16 | - cron: '0 0 * * 2' 17 | 18 | jobs: 19 | check_token: 20 | name: "Check SANDPAPER_WORKFLOW token" 21 | runs-on: ubuntu-22.04 22 | outputs: 23 | workflow: ${{ steps.validate.outputs.wf }} 24 | repo: ${{ steps.validate.outputs.repo }} 25 | steps: 26 | - name: "validate token" 27 | id: validate 28 | uses: carpentries/actions/check-valid-credentials@main 29 | with: 30 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 31 | 32 | update_workflow: 33 | name: "Update Workflow" 34 | runs-on: ubuntu-22.04 35 | needs: check_token 36 | if: ${{ needs.check_token.outputs.workflow == 'true' }} 37 | steps: 38 | - name: "Checkout Repository" 39 | uses: actions/checkout@v4 40 | 41 | - name: Update Workflows 42 | id: update 43 | uses: carpentries/actions/update-workflows@main 44 | with: 45 | clean: ${{ github.event.inputs.clean }} 46 | 47 | - name: Create Pull Request 48 | id: cpr 49 | if: "${{ steps.update.outputs.new }}" 50 | uses: carpentries/create-pull-request@main 51 | with: 52 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 53 | delete-branch: true 54 | branch: "update/workflows" 55 | commit-message: "[actions] update sandpaper workflow to version ${{ steps.update.outputs.new }}" 56 | title: "Update Workflows to Version ${{ steps.update.outputs.new }}" 57 | body: | 58 | :robot: This is an automated build 59 | 60 | Update Workflows from sandpaper version ${{ steps.update.outputs.old }} -> ${{ steps.update.outputs.new }} 61 | 62 | - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} 63 | 64 | [1]: https://github.com/carpentries/create-pull-request/tree/main 65 | labels: "type: template and tools" 66 | draft: false 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # sandpaper files 2 | episodes/*html 3 | site/* 4 | !site/README.md 5 | 6 | # History files 7 | .Rhistory 8 | .Rapp.history 9 | # Session Data files 10 | .RData 11 | # User-specific files 12 | .Ruserdata 13 | # Example code in package build process 14 | *-Ex.R 15 | # Output files from R CMD build 16 | /*.tar.gz 17 | # Output files from R CMD check 18 | /*.Rcheck/ 19 | # RStudio files 20 | .Rproj.user/ 21 | # produced vignettes 22 | vignettes/*.html 23 | vignettes/*.pdf 24 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 25 | .httr-oauth 26 | # knitr and R markdown default cache directories 27 | *_cache/ 28 | /cache/ 29 | # Temporary files created by R markdown 30 | *.utf8.md 31 | *.knit.md 32 | # R Environment Variables 33 | .Renviron 34 | # pkgdown site 35 | docs/ 36 | # translation temp files 37 | po/*~ 38 | # renv detritus 39 | renv/sandbox/ 40 | *.pyc 41 | *~ 42 | .DS_Store 43 | .ipynb_checkpoints 44 | .sass-cache 45 | __pycache__ 46 | _site 47 | /Gemfile.lock 48 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Abigail Cabunoc 2 | Erin Becker ErinBecker 3 | Francois Michonneau 4 | Greg Wilson 5 | Nick Young 6 | Raniere Silva 7 | Raniere Silva 8 | Rémi Emonet 9 | Tracy Teal 10 | Tracy Teal 11 | Laurent Gatto Laurent 12 | Ben Marwick 13 | Kari L. Jordan 14 | Francisco Rodriguez-Sanchez 15 | Christie Bahlai 16 | Martin Dreyer 17 | Amy Nurnberger 18 | Jaclyn Saunders 19 | Karen Cranston 20 | Timothée Poisot 21 | Christina Koch 22 | Geoffrey Boushey 23 | Maneesha Sane 24 | Saira Kazmi -------------------------------------------------------------------------------- /.update-copyright.conf: -------------------------------------------------------------------------------- 1 | [project] 2 | vcs: Git 3 | 4 | [files] 5 | authors: yes 6 | files: no 7 | -------------------------------------------------------------------------------- /.zenodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "contributors": [ 3 | { 4 | "type": "Editor", 5 | "name": "Fabrice Rwasimitana", 6 | "orcid": "0000-0003-3064-2365" 7 | }, 8 | { 9 | "type": "Editor", 10 | "name": "Juan A. Ugalde", 11 | "orcid": "0000-0001-6638-0817" 12 | }, 13 | { 14 | "type": "Editor", 15 | "name": "Ethan P. White", 16 | "orcid": "0000-0001-6728-7745" 17 | } 18 | ], 19 | "creators": [ 20 | { 21 | "name": "Erin Alison Becker", 22 | "orcid": "0000-0002-6832-0233" 23 | }, 24 | { 25 | "name": "Tracy Teal", 26 | "orcid": "0000-0002-9180-9598" 27 | }, 28 | { 29 | "name": "Ben Companjen" 30 | }, 31 | { 32 | "name": "Ethan P. White", 33 | "orcid": "0000-0001-6728-7745" 34 | }, 35 | { 36 | "name": "Kari L. Jordan, PhD", 37 | "orcid": "0000-0003-4121-2432" 38 | }, 39 | { 40 | "name": "Katrin Leinweber", 41 | "orcid": "0000-0001-5135-5758" 42 | }, 43 | { 44 | "name": "Luis J Villanueva" 45 | } 46 | ], 47 | "license": { 48 | "id": "CC-BY-4.0" 49 | } 50 | } -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | ecology-workshop was written by: 2 | Abigail Cabunoc 3 | Adam Obeng 4 | Bill Mills 5 | Erin Becker 6 | Ethan White 7 | Francois Michonneau 8 | Gabriel A. Devenyi 9 | Greg Wilson 10 | Ian Carroll 11 | James Allen 12 | Jeffrey W. Hollister 13 | Jon Pipitone 14 | Jonah Duckles 15 | Karen Cranston 16 | Maxim Belkin 17 | Michael Hansen 18 | Nick Young 19 | Piotr Banaszkiewicz 20 | Raniere Silva 21 | Rémi Emonet 22 | Timothée Poisot 23 | Tracy Teal 24 | W. Trevor King 25 | evanwill 26 | -------------------------------------------------------------------------------- /CITATION: -------------------------------------------------------------------------------- 1 | Please cite as: 2 | 3 | Tracy Teal (eds): "Data Carpentry: Ecology Workshop overview." 4 | Version 2017.04.0, April 2017, 5 | http://www.datacarpentry.org/ecology-workshop/, 6 | FIXME: Add Zenodo DOI. 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Contributor Code of Conduct" 3 | --- 4 | 5 | As contributors and maintainers of this project, 6 | we pledge to follow the [The Carpentries Code of Conduct][coc]. 7 | 8 | Instances of abusive, harassing, or otherwise unacceptable behavior 9 | may be reported by following our [reporting guidelines][coc-reporting]. 10 | 11 | [coc]: https://docs.carpentries.org/topic_folders/policies/code-of-conduct.html 12 | [coc-reporting]: https://docs.carpentries.org/topic_folders/policies/incident-reporting.html 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | [The Carpentries][cp-site] ([Software Carpentry][swc-site], [Data 4 | Carpentry][dc-site], and [Library Carpentry][lc-site]) are open source 5 | projects, and we welcome contributions of all kinds: new lessons, fixes to 6 | existing material, bug reports, and reviews of proposed changes are all 7 | welcome. 8 | 9 | ### Contributor Agreement 10 | 11 | By contributing, you agree that we may redistribute your work under [our 12 | license](LICENSE.md). In exchange, we will address your issues and/or assess 13 | your change proposal as promptly as we can, and help you become a member of our 14 | community. Everyone involved in [The Carpentries][cp-site] agrees to abide by 15 | our [code of conduct](CODE_OF_CONDUCT.md). 16 | 17 | ### How to Contribute 18 | 19 | The easiest way to get started is to file an issue to tell us about a spelling 20 | mistake, some awkward wording, or a factual error. This is a good way to 21 | introduce yourself and to meet some of our community members. 22 | 23 | 1. If you do not have a [GitHub][github] account, you can [send us comments by 24 | email][contact]. However, we will be able to respond more quickly if you use 25 | one of the other methods described below. 26 | 27 | 2. If you have a [GitHub][github] account, or are willing to [create 28 | one][github-join], but do not know how to use Git, you can report problems 29 | or suggest improvements by [creating an issue][repo-issues]. This allows us 30 | to assign the item to someone and to respond to it in a threaded discussion. 31 | 32 | 3. If you are comfortable with Git, and would like to add or change material, 33 | you can submit a pull request (PR). Instructions for doing this are 34 | [included below](#using-github). For inspiration about changes that need to 35 | be made, check out the [list of open issues][issues] across the Carpentries. 36 | 37 | Note: if you want to build the website locally, please refer to [The Workbench 38 | documentation][template-doc]. 39 | 40 | ### Where to Contribute 41 | 42 | 1. If you wish to change this lesson, add issues and pull requests here. 43 | 2. If you wish to change the template used for workshop websites, please refer 44 | to [The Workbench documentation][template-doc]. 45 | 46 | ### What to Contribute 47 | 48 | There are many ways to contribute, from writing new exercises and improving 49 | existing ones to updating or filling in the documentation and submitting [bug 50 | reports][issues] about things that do not work, are not clear, or are missing. 51 | If you are looking for ideas, please see [the list of issues for this 52 | repository][repo-issues], or the issues for [Data Carpentry][dc-issues], 53 | [Library Carpentry][lc-issues], and [Software Carpentry][swc-issues] projects. 54 | 55 | Comments on issues and reviews of pull requests are just as welcome: we are 56 | smarter together than we are on our own. **Reviews from novices and newcomers 57 | are particularly valuable**: it's easy for people who have been using these 58 | lessons for a while to forget how impenetrable some of this material can be, so 59 | fresh eyes are always welcome. 60 | 61 | ### What *Not* to Contribute 62 | 63 | Our lessons already contain more material than we can cover in a typical 64 | workshop, so we are usually *not* looking for more concepts or tools to add to 65 | them. As a rule, if you want to introduce a new idea, you must (a) estimate how 66 | long it will take to teach and (b) explain what you would take out to make room 67 | for it. The first encourages contributors to be honest about requirements; the 68 | second, to think hard about priorities. 69 | 70 | We are also not looking for exercises or other material that only run on one 71 | platform. Our workshops typically contain a mixture of Windows, macOS, and 72 | Linux users; in order to be usable, our lessons must run equally well on all 73 | three. 74 | 75 | ### Using GitHub 76 | 77 | If you choose to contribute via GitHub, you may want to look at [How to 78 | Contribute to an Open Source Project on GitHub][how-contribute]. In brief, we 79 | use [GitHub flow][github-flow] to manage changes: 80 | 81 | 1. Create a new branch in your desktop copy of this repository for each 82 | significant change. 83 | 2. Commit the change in that branch. 84 | 3. Push that branch to your fork of this repository on GitHub. 85 | 4. Submit a pull request from that branch to the [upstream repository][repo]. 86 | 5. If you receive feedback, make changes on your desktop and push to your 87 | branch on GitHub: the pull request will update automatically. 88 | 89 | NB: The published copy of the lesson is usually in the `main` branch. 90 | 91 | Each lesson has a team of maintainers who review issues and pull requests or 92 | encourage others to do so. The maintainers are community volunteers, and have 93 | final say over what gets merged into the lesson. 94 | 95 | ### Other Resources 96 | 97 | The Carpentries is a global organisation with volunteers and learners all over 98 | the world. We share values of inclusivity and a passion for sharing knowledge, 99 | teaching and learning. There are several ways to connect with The Carpentries 100 | community listed at [https://carpentries.org/connect/](https://carpentries.org/connect/) including via social 101 | media, slack, newsletters, and email lists. You can also [reach us by 102 | email][contact]. 103 | 104 | [cp-site]: https://carpentries.org/ 105 | [swc-site]: https://software-carpentry.org/ 106 | [dc-site]: https://datacarpentry.org/ 107 | [lc-site]: https://librarycarpentry.org/ 108 | [github]: https://github.com 109 | [contact]: mailto:team@carpentries.org 110 | [github-join]: https://github.com/join 111 | [repo-issues]: https://github.com/datacarpentry/ecology-workshop/issues 112 | [issues]: https://carpentries.org/help-wanted-issues/ 113 | [template-doc]: https://carpentries.github.io/workbench/ 114 | [dc-issues]: https://github.com/issues?q=user%3Adatacarpentry 115 | [lc-issues]: https://github.com/issues?q=user%3ALibraryCarpentry 116 | [swc-issues]: https://github.com/issues?q=user%3Aswcarpentry 117 | [how-contribute]: https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github 118 | [github-flow]: https://guides.github.com/introduction/flow/ 119 | [repo]: https://github.com/datacarpentry/ecology-workshop 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Licenses" 3 | --- 4 | 5 | ## Instructional Material 6 | 7 | All Carpentries (Software Carpentry, Data Carpentry, and Library Carpentry) 8 | instructional material is made available under the [Creative Commons 9 | Attribution license][cc-by-human]. The following is a human-readable summary of 10 | (and not a substitute for) the [full legal text of the CC BY 4.0 11 | license][cc-by-legal]. 12 | 13 | You are free: 14 | 15 | - to **Share**\---copy and redistribute the material in any medium or format 16 | - to **Adapt**\---remix, transform, and build upon the material 17 | 18 | for any purpose, even commercially. 19 | 20 | The licensor cannot revoke these freedoms as long as you follow the license 21 | terms. 22 | 23 | Under the following terms: 24 | 25 | - **Attribution**\---You must give appropriate credit (mentioning that your work 26 | is derived from work that is Copyright (c) The Carpentries and, where 27 | practical, linking to [https://carpentries.org/](https://carpentries.org/)), provide a [link to the 28 | license][cc-by-human], and indicate if changes were made. You may do so in 29 | any reasonable manner, but not in any way that suggests the licensor endorses 30 | you or your use. 31 | 32 | - **No additional restrictions**\---You may not apply legal terms or 33 | technological measures that legally restrict others from doing anything the 34 | license permits. With the understanding that: 35 | 36 | Notices: 37 | 38 | - You do not have to comply with the license for elements of the material in 39 | the public domain or where your use is permitted by an applicable exception 40 | or limitation. 41 | - No warranties are given. The license may not give you all of the permissions 42 | necessary for your intended use. For example, other rights such as publicity, 43 | privacy, or moral rights may limit how you use the material. 44 | 45 | ## Software 46 | 47 | Except where otherwise noted, the example programs and other software provided 48 | by The Carpentries are made available under the [OSI][osi]\-approved [MIT 49 | license][mit-license]. 50 | 51 | Permission is hereby granted, free of charge, to any person obtaining a copy of 52 | this software and associated documentation files (the "Software"), to deal in 53 | the Software without restriction, including without limitation the rights to 54 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 55 | of the Software, and to permit persons to whom the Software is furnished to do 56 | so, subject to the following conditions: 57 | 58 | The above copyright notice and this permission notice shall be included in all 59 | copies or substantial portions of the Software. 60 | 61 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 62 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 63 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 65 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 66 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 67 | SOFTWARE. 68 | 69 | ## Trademark 70 | 71 | "The Carpentries", "Software Carpentry", "Data Carpentry", and "Library 72 | Carpentry" and their respective logos are registered trademarks of 73 | [The Carpentries, Inc.][carpentries]. 74 | 75 | [cc-by-human]: https://creativecommons.org/licenses/by/4.0/ 76 | [cc-by-legal]: https://creativecommons.org/licenses/by/4.0/legalcode 77 | [mit-license]: https://opensource.org/licenses/mit-license.html 78 | [carpentries]: https://carpentries.org 79 | [osi]: https://opensource.org 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | ## Data Carpentry Ecology Workshop overview 2017.04.0 2 | 3 | Initial release of the Data Carpentry Ecology Workshop overview 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ecology-workshop 2 | 3 | ## Overview of the ecology workshop 4 | 5 | Data Carpentry's aim is to teach researchers basic concepts, skills, and tools for working with data so that they can get more done in less time, and with less pain. This workshop uses a tabular ecology dataset and teaches data cleaning, management, analysis and visualization. There are no pre-requisites, and the materials assume no prior knowledge about the tools. 6 | 7 | The workshop uses a single tabular data set that contains observations about adorable small mammals over a long period of time in Arizona. See `data.md` for more information about this data set, including the download location. 8 | 9 | The workshop can be taught using R or Python as the base language. 10 | 11 | Overview of the lessons: 12 | 13 | 1. Data organization in spreadsheets and data cleaning with OpenRefine 14 | 15 | - Introduction to R or Python 16 | - Data analysis and visualization in R or Python 17 | - SQL for data management 18 | 19 | An example of the ecology materials in the wild is this [Data Carpentry workshop at CalTech](https://datacarpentry.org/2015-11-23-caltech/) in 2015. 20 | 21 | ## Detailed structure 22 | 23 | ### Day 1 morning: Data organization \& cleaning 24 | 25 | There are two lessons in this section. The first is a spreadsheet lesson that teaches good data organization, and some data cleaning and quality control checking in a spreadsheet program. 26 | 27 | - [spreadsheet lesson](https://datacarpentry.org/spreadsheet-ecology-lesson/) 28 | - [spreadsheet repository](https://github.com/datacarpentry/spreadsheet-ecology-lesson) 29 | 30 | The second lesson uses a spreadsheet-like program called [OpenRefine](https://openrefine.org/) to teach data cleaning and filtering, and to introduce scripting, regular expressions and APIs (application programming interfaces). 31 | 32 | - [OpenRefine lesson](https://datacarpentry.org/OpenRefine-ecology-lesson/) 33 | - [OpenRefine repository](https://github.com/datacarpentry/OpenRefine-ecology-lesson) 34 | 35 | ### Day 1 afternoon and Day 2 morning: Data analysis \& visualization 36 | 37 | These lessons includes a basic introduction to R or Python syntax, importing CSV data, and subsetting and merging data. It finishes with calculating summary statistics and creating simple plots. 38 | 39 | - [R lesson](https://datacarpentry.org/R-ecology-lesson/) and [Python lesson](https://datacarpentry.org/python-ecology-lesson/) 40 | - [R repository](https://github.com/datacarpentry/R-ecology-lesson) and [Python repository](https://github.com/datacarpentry/python-ecology-lesson) 41 | 42 | ### Day 2 afternoon: Data management with SQL 43 | 44 | This lesson introduces the concept of a database using SQLite, how to structure data for easy database import, and how to import tabular data into SQLite. Then, it teaches basic queries, combining results and doing queries across multiple tables. 45 | 46 | - [SQL lesson](https://datacarpentry.org/sql-ecology-lesson/) 47 | - [SQL repository](https://github.com/datacarpentry/sql-ecology-lesson) 48 | 49 | ## Other lessons 50 | 51 | There are a number of other ecology lessons that are not part of the base workshop. Some of these are no longer taught, and some are only taught at extended workshops. 52 | 53 | - [shell-ecology](https://github.com/datacarpentry/shell-ecology) 54 | - [R-dplyr-ecology-archived](https://github.com/datacarpentry/R-dplyr-ecology-archived) 55 | - [scripting-ecology](https://github.com/datacarpentry/scripting-ecology) 56 | - [R-ggplot2-ecology](https://github.com/datacarpentry/R-ggplot2-ecology) 57 | 58 | 59 | -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # Values for this lesson. 3 | #------------------------------------------------------------ 4 | 5 | # Which carpentry is this (swc, dc, lc, or cp)? 6 | # swc: Software Carpentry 7 | # dc: Data Carpentry 8 | # lc: Library Carpentry 9 | # cp: Carpentries (to use for instructor training for instance) 10 | # incubator: The Carpentries Incubator 11 | carpentry: 'dc' 12 | 13 | # Overall title for pages. 14 | title: 'Ecology Workshop Overview' 15 | 16 | # Date the lesson was created (YYYY-MM-DD, this is empty by default) 17 | created: '2015-12-12' 18 | 19 | # Comma-separated list of keywords for the lesson 20 | keywords: 'software, data, lesson, The Carpentries' # FIXME 21 | 22 | # Life cycle stage of the lesson 23 | # possible values: pre-alpha, alpha, beta, stable 24 | life_cycle: 'stable' 25 | 26 | # License of the lesson 27 | license: 'CC-BY 4.0' 28 | 29 | # Link to the source repository for this lesson 30 | source: 'https://github.com/datacarpentry/ecology-workshop' 31 | 32 | # Default branch of your lesson 33 | branch: 'main' 34 | 35 | # Who to contact if there are any issues 36 | contact: 'team@carpentries.org' 37 | 38 | # Navigation ------------------------------------------------ 39 | # 40 | # Use the following menu items to specify the order of 41 | # individual pages in each dropdown section. Leave blank to 42 | # include all pages in the folder. 43 | # 44 | # Example ------------- 45 | # 46 | # episodes: 47 | # - introduction.md 48 | # - first-steps.md 49 | # 50 | # learners: 51 | # - setup.md 52 | # 53 | # instructors: 54 | # - instructor-notes.md 55 | # 56 | # profiles: 57 | # - one-learner.md 58 | # - another-learner.md 59 | 60 | # Order of episodes in your lesson 61 | episodes: 62 | - introduction.Rmd 63 | 64 | # Information for Learners 65 | learners: 66 | 67 | # Information for Instructors 68 | instructors: 69 | 70 | # Learner Profiles 71 | profiles: 72 | 73 | # Customisation --------------------------------------------- 74 | # 75 | # This space below is where custom yaml items (e.g. pinning 76 | # sandpaper and varnish versions) should live 77 | 78 | 79 | url: 'https://datacarpentry.github.io/ecology-workshop' 80 | analytics: 'carpentries' 81 | lang: 'en' 82 | overview: true 83 | -------------------------------------------------------------------------------- /files/setup-data.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ## Data 6 | 7 | You can download all of the data used in this workshop by clicking 8 | [this download link](https://ndownloader.figshare.com/articles/1314459/versions/9). The file is 38.4 MB. 9 | 10 | Clicking the download link will automatically download all of the files to your default download directory as a single compressed 11 | (`.zip`) file. To expand this file, double click the folder icon in your file navigator application (for Macs, this is the Finder 12 | application). 13 | 14 | For a full description of the data used in this workshop see the [data page](learners/data.md). 15 | 16 | 17 | -------------------------------------------------------------------------------- /files/setup-openrefine.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ### OpenRefine 6 | 7 | - OpenRefine is a Java program that runs on your local machine (not on the cloud). Although it displays in your browser, no web 8 | connection is needed and your data remains local. You need to have a ‘Java Runtime Environment' (JRE) installed on your computer to run 9 | OpenRefine. If you don't already have one installed and are running Windows, then you can download the "Windows kit with embedded Java" version from the downloads page. You can also download and install Java from [https://java.com](https://java.com) by going to the site and clicking "Free Java Download". 10 | 11 | - To install OpenRefine, go to their [download page](https://openrefine.org/download.html). From the download page, select either "Windows 12 | kit", "Mac kit", or "Linux kit" - depending on your operating system - and follow the instructions next to your download link. This 13 | lesson has been tested with the recent versions of OpenRefine, at least 3.4.1. **If you are using an older version, it is 14 | recommended you upgrade to the latest tested version.** 15 | 16 | - You may get an error message: "OpenRefine.app can't be opened because it is from an unidentified developer." If you get this message, 17 | open your system preferences and click "Security \& Privacy". You will see a message "OpenRefine.app was blocked from opening because it 18 | is from an unidentified developer." Click "Open Anyway" and "Yes". OpenRefine should open in your default web browser. 19 | 20 | - OpenRefine does not support Internet Explorer or Edge. Please use Firefox, Chrome or Safari instead. 21 | 22 | 23 | -------------------------------------------------------------------------------- /files/setup-overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ## Overview 6 | 7 | This workshop is designed to be run on your laptop. First, you will need to download the data we use in the workshop. Then, you need to 8 | install some software. After following the instructions on this page, you should have everything you need to participate fully in the 9 | workshop! 10 | 11 | 12 | -------------------------------------------------------------------------------- /files/setup-python.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ### Python and Jupyter Notebooks 6 | 7 | [Python](https://python.org) is a popular language for scientific computing, and great for general-purpose programming as well. 8 | For this workshop we use Python version 3.x. 9 | Installing all of its scientific packages individually can be a bit difficult, so we provide an environment file to help you take care of them all together. 10 | We will use the _Miniforge_ distribution of Python. 11 | 12 | Please refer to the [Python section of the workshop website for installation instructions](https://carpentries.github.io/workshop-template/install_instructions/#python). 13 | 14 | #### Launching Jupyter 15 | 16 | :::::::::::::::::::::::::::::::::::::::::: spoiler 17 | 18 | ##### Windows 19 | 20 | After following the instructions above, search for the application 'Miniforge Prompt' and open it. 21 | Type the following commands, pressing Enter after each one: 22 | 23 | ```bash 24 | conda activate carpentries 25 | jupyter notebook 26 | ``` 27 | 28 | :::::::::::::::::::::::::::::::::::::::::::::::::: 29 | 30 | :::::::::::::::::::::::::::::::::::::::::: spoiler 31 | 32 | ##### MacOS 33 | 34 | After following the instructions above, open the Terminal application (inside Applications/Utilities). 35 | Type the following commands, pressing Enter after each one: 36 | 37 | ```bash 38 | conda activate carpentries 39 | jupyter notebook 40 | ``` 41 | :::::::::::::::::::::::::::::::::::::::::::::::::: 42 | 43 | :::::::::::::::::::::::::::::::::::::::::: spoiler 44 | 45 | ##### Linux 46 | 47 | After following the instructions above, search for the application 'Miniforge Prompt' and open it. 48 | Type the following commands, pressing Enter after each one: 49 | 50 | ```bash 51 | conda activate carpentries 52 | jupyter notebook 53 | ``` 54 | 55 | :::::::::::::::::::::::::::::::::::::::::::::::::: 56 | 57 | The notebook should open automatically in your browser. 58 | If it does not or you wish to use a different browser, open this link: [http://localhost:8888](https://localhost:8888). 59 | 60 | For a brief introduction to Jupyter Notebooks, please consult our 61 | [Introduction to Jupyter Notebooks](https://datacarpentry.org/python-ecology-lesson/jupyter_notebooks/) page. 62 | 63 | 64 | -------------------------------------------------------------------------------- /files/setup-r.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ### R and RStudio 6 | 7 | - R and RStudio are separate downloads and installations. R is the 8 | underlying statistical computing environment, but using R alone is no 9 | fun. RStudio is a graphical integrated development environment (IDE) that makes 10 | using R much easier and more interactive. You need to install R before you 11 | install RStudio. After installing both programs, you will need to install 12 | some specific R packages within RStudio. Follow the instructions below for 13 | your operating system, and then follow the instructions to install 14 | **`tidyverse`** and **`RSQLite`**. 15 | 16 | #### Windows 17 | 18 | :::::::::::::::: spoiler 19 | 20 | ## If you already have R and RStudio installed 21 | 22 | - Open RStudio, and click on "Help" > "Check for updates". If a new version is 23 | available, quit RStudio, and download the latest version for RStudio. 24 | 25 | - To check which version of R you are using, start RStudio and the first thing 26 | that appears in the console indicates the version of R you are 27 | running. Alternatively, you can type `sessionInfo()`, which will also display 28 | which version of R you are running. Go on 29 | the [CRAN website](https://cran.r-project.org/bin/windows/base/) and check 30 | whether a more recent version is available. If so, please download and install 31 | it. You can [check here](https://cran.r-project.org/bin/windows/base/rw-FAQ.html#How-do-I-UNinstall-R_003f) for 32 | more information on how to remove old versions from your system if you wish to do so. 33 | 34 | - Follow the steps in the instructions [for everyone](#for-everyone) at the 35 | bottom of this page. 36 | 37 | 38 | ::::::::::::::::::::::::: 39 | 40 | :::::::::::::::: spoiler 41 | 42 | ## If you don't have R and RStudio installed 43 | 44 | - Download R from 45 | the [CRAN website](https://cran.r-project.org/bin/windows/base/release.htm). 46 | 47 | - Run the `.exe` file that was just downloaded 48 | 49 | - Go to the [RStudio download page](https://www.rstudio.com/products/rstudio/download/#download) 50 | 51 | - Under *Installers* select **RStudio x.yy.zzz - Windows Vista/7/8/10** (where x, y, and z represent version numbers) 52 | 53 | - Double click the file to install it 54 | 55 | - Once it's installed, open RStudio to make sure it works and you don't get any 56 | error messages 57 | 58 | - Follow the steps in the instructions [for everyone](#for-everyone) at the 59 | bottom of this page. 60 | 61 | 62 | ::::::::::::::::::::::::: 63 | 64 | #### macOS 65 | 66 | :::::::::::::::: spoiler 67 | 68 | ## If you already have R and RStudio installed 69 | 70 | - Open RStudio, and click on "Help" > "Check for updates". If a new version is 71 | available, quit RStudio, and download the latest version for RStudio. 72 | 73 | - To check the version of R you are using, start RStudio and the first thing 74 | that appears on the terminal indicates the version of R you are running. Alternatively, you can type `sessionInfo()`, which will 75 | also display which version of R you are running. Go on 76 | the [CRAN website](https://cran.r-project.org/bin/macosx/) and check 77 | whether a more recent version is available. If so, please download and install 78 | it. 79 | 80 | - Follow the steps in the instructions [for everyone](#for-everyone) at the 81 | bottom of this page. 82 | 83 | 84 | ::::::::::::::::::::::::: 85 | 86 | :::::::::::::::: spoiler 87 | 88 | ## If you don't have R and RStudio installed 89 | 90 | - Download R from 91 | the [CRAN website](https://cran.r-project.org/bin/macosx/). 92 | 93 | - Select the `.pkg` file for the latest R version 94 | 95 | - Double click on the downloaded file to install R 96 | 97 | - It is also a good idea to install [XQuartz](https://www.xquartz.org/) (needed 98 | by some packages) 99 | 100 | - Go to the [RStudio download page](https://www.rstudio.com/products/rstudio/download/#download) 101 | 102 | - Under *Installers* select **RStudio x.yy.zzz - Mac OS X 10.6+ (64-bit)** 103 | (where x, y, and z represent version numbers) 104 | 105 | - Double click the file to install RStudio 106 | 107 | - Once it's installed, open RStudio to make sure it works and you don't get any 108 | error messages. 109 | 110 | - Follow the steps in the instructions [for everyone](#for-everyone) at the 111 | bottom of this page. 112 | 113 | 114 | ::::::::::::::::::::::::: 115 | 116 | #### Linux 117 | 118 | - Follow the instructions for your distribution 119 | from [CRAN](https://cloud.r-project.org/bin/linux), they provide information 120 | to get the most recent version of R for common distributions. For most 121 | distributions, you could use your package manager (e.g., for Debian/Ubuntu run 122 | `sudo apt-get install r-base`, and for Fedora `sudo yum install R`), but we 123 | don't recommend this approach as the versions provided by this are 124 | usually out of date. In any case, make sure you have at least R 3.5.1. 125 | - Go to the [RStudio download 126 | page](https://www.rstudio.com/products/rstudio/download/#download) 127 | - Under *Installers* select the version that matches your distribution, and 128 | install it with your preferred method (e.g., with Debian/Ubuntu `sudo dpkg -i rstudio-x.yy.zzz-amd64.deb` at the terminal). 129 | - Once it's installed, open RStudio to make sure it works and you don't get any 130 | error messages. 131 | - Follow the steps in the [instructions for everyone](#for-everyone) 132 | 133 | #### For everyone 134 | 135 | - After installing R and RStudio, you need to install the `tidyverse` and 136 | `RSQLite` packages. Start RStudio by double-clicking the icon and then type: 137 | `install.packages(c("tidyverse", "RSQLite"))`. You can also do this by going to Tools -> Install Packages and 138 | typing the names of the packages you want to install, separated by a comma. 139 | 140 | 141 | -------------------------------------------------------------------------------- /files/setup-spreadsheet.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ### Spreadsheet program 6 | 7 | - To interact with spreadsheets, we can use LibreOffice, Microsoft Excel, Gnumeric, OpenOffice.org, or other programs. 8 | Commands may differ a bit between programs, but the general ideas for thinking about spreadsheets are the same. For this workshop, 9 | we recommend using either Microsoft Excel (paid software) or LibreOffice (free and open source). Other spreadsheet programs may 10 | not have all of the features we will be exploring in this workshop. 11 | 12 | - To install LibreOffice, go to their [download page](https://www.libreoffice.org/download/download/). The website should 13 | automatically select the correct option for your operating system. Click the "Download" button. You will go to a page that asks about a 14 | donation, but you don't need to make one. Your download should begin automatically. Once the installer is downloaded, double click on it (you may need to open your Downloads folder) and LibreOffice should install. 15 | 16 | 17 | -------------------------------------------------------------------------------- /files/setup-sql.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ## SQL 6 | 7 | - SQL is a specialized programming language used with databases. We 8 | use a simple database manager called [SQLite](https://www.sqlite.org/) 9 | in our lessons. We will use the [DB Browser for SQLite](https://sqlitebrowser.org/) program, 10 | which is available for all major platforms. 11 | 12 | - To install the DB Browser, go to their [download page](https://sqlitebrowser.org/dl/) and choose the correct installer for 13 | your operating system. Once the installer is downloaded, double click on it (you may need to open your Downloads folder), follow 14 | any other instructions that appear, and 15 | DB Browser should install. After installing, you can delete the installer `.dmg` file. 16 | 17 | 18 | -------------------------------------------------------------------------------- /in.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: lesson 3 | root: . 4 | --- 5 | FIXME: home page introduction 6 | 7 | > ## Prerequisites 8 | > 9 | > FIXME 10 | {: .prereq} 11 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: index.html 3 | site: sandpaper::sandpaper_site 4 | --- 5 | 6 | Data Carpentry's aim is to teach researchers basic concepts, skills, and tools for working with data so that they can get more done in less time, and with less pain. This workshop uses a tabular ecology dataset and teaches data cleaning, management, analysis and visualization. 7 | 8 | :::::::::::::::::::::::::::::::::::::::::: prereq 9 | 10 | ## Getting Started 11 | 12 | Data Carpentry's teaching is hands-on, so participants are encouraged to use 13 | their own computers to ensure the proper setup of tools for an efficient 14 | workflow. To most effectively use these materials, please make sure to download 15 | the data and install everything before working through this lesson. 16 | 17 | This workshop assumes no prior experience with the tools covered in the workshop. 18 | 19 | To get started, follow the directions in the [Setup](#setup-instructions-for-your-workshop) tab to 20 | get access to the required software and data for this workshop. 21 | 22 | :::::::::::::::::::::::::::::::::::::::::::::::::: 23 | 24 | :::::::::::::::::::::::::::::::::::::::::: prereq 25 | 26 | ## Data 27 | 28 | The data for this workshop are is the [Portal Project Teaching Database](https://figshare.com/articles/Portal_Project_Teaching_Database/1314459) available on FigShare, with a CC-BY license available for reuse. 29 | 30 | The Portal Project Teaching Database is a simplified version of the Portal 31 | Project Database designed for teaching. It is a tabular dataset of observations 32 | of small mammals in a desert ecosystem in Arizona, USA, collected over more than 40 years. 33 | It provides a real world example of 34 | life-history, population, and ecological data, with sufficient complexity to 35 | teach many aspects of data analysis and management, but with many complexities 36 | removed to allow students to focus on the core ideas and skills being taught. 37 | 38 | [More information on this dataset](data.md) 39 | 40 | :::::::::::::::::::::::::::::::::::::::::::::::::: 41 | 42 | # Workshop Overview 43 | 44 | The workshop can be taught using R or Python as the base language. All workshops start with a lesson on organizing data effectively in 45 | spreadsheets, followed by a lesson on data cleaning with OpenRefine. Each workshop will then include **either** a lesson on R **or** a 46 | lesson on Python. Both the R and Python lessons focus on data import, exploratory data analysis, and visualization. Workshops may also 47 | include a lesson on working with data in a relational database using SQL, at the discretion of the instructors. 48 | 49 | | Lesson | Overview | 50 | | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | 51 | | [Data Organization in Spreadsheets for Ecologists](https://datacarpentry.org/spreadsheet-ecology-lesson/) | Learn how to organize tabular data, handle date formatting, carry out quality control and quality assurance and export data to use with downstream applications. | 52 | | [Data Cleaning with OpenRefine for Ecologists ](https://datacarpentry.org/OpenRefine-ecology-lesson/) | Explore, summarize, and clean tabular data reproducibly. | 53 | | [Data Analysis and Visualization in R for Ecologists](https://datacarpentry.org/R-ecology-lesson/) | Import data into R, calculate summary statistics, and create publication-quality graphics. | 54 | | [Data Analysis and Visualization with Python for Ecologists](https://datacarpentry.org/python-ecology-lesson/) | Import data into Python, calculate summary statistics, and create publication-quality graphics. | 55 | | [Data Management with SQL for Ecologists ](https://datacarpentry.org/sql-ecology-lesson/) | Structure data for database import. Query data within a relational database. | 56 | 57 | 58 | -------------------------------------------------------------------------------- /instructors/instructor-notes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Instructor Notes 3 | --- 4 | 5 | FIXME 6 | 7 | 8 | -------------------------------------------------------------------------------- /learners/data.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Workshop Data 3 | --- 4 | 5 | All of the ecology lessons use the same data set throughout. The data is tabular (rows and columns), similar in structure to what you might have in a spreadsheet. 6 | 7 | ## The Portal Project Teaching Database 8 | 9 | Available on FigShare: [http://figshare.com/articles/Portal\_Project\_Teaching\_Database/1314459](https://figshare.com/articles/Portal_Project_Teaching_Database/1314459) 10 | 11 | The data used in the ecology lessons is a time-series for a small mammal community 12 | in southern Arizona. This is part of a project studying the effects of rodents 13 | and ants on the plant community that has been running for almost 40 years. The 14 | rodents are sampled on a series of 24 plots, with different experimental 15 | manipulations controlling which rodents are allowed to access which plots. 16 | 17 | This is a real dataset that has been used in over 100 publications. We've simplified 18 | it just a little bit for the workshop, but you can download the full dataset and work 19 | with it using exactly the same tools we'll learn about today. 20 | 21 | :::::::::::::::::::::::::::::::::::::::::: prereq 22 | 23 | ## Portal Project Teaching Dataset 24 | 25 | The Portal Project Teaching Database is a simplified version of the Portal Project Database designed for teaching. It provides a real world example of life-history, population, and ecological data, with sufficient complexity to teach many aspects of data analysis and management, but with many complexities removed to allow students to focus on the core ideas and skills being taught. 26 | 27 | The database is currently available in csv, json, and sqlite. 28 | 29 | This database is not designed for research as it intentionally removes some of the real-world complexities. The original database is published at [Ecological Archives](https://esapubs.org/archive/ecol/E090/118/) and this version of the database should be used for research purposes. The Python code used for converting the original database to this teach version is included as 'create\_portal\_teach\_dataset.py'. Suggested changes or additions to this dataset can be requested or contributed in the project GitHub repository [https://github.com/weecology/portal-teachingdb](https://github.com/weecology/portal-teachingdb). 30 | 31 | **CITATION:** Ernest, Morgan; Brown, James; Valone, Thomas; White, Ethan P. (2017): Portal Project Teaching Database. figshare. [https://doi.org/10.6084/m9.figshare.1314459.v6](https://doi.org/10.6084/m9.figshare.1314459.v6) 32 | 33 | :::::::::::::::::::::::::::::::::::::::::::::::::: 34 | 35 | Files we use in this dataset: 36 | 37 | - [surveys.csv](https://ndownloader.figshare.com/files/2292172) - the survey data 38 | Fields: record\_id, month, day, year, plot\_id, species\_id, sex, hindfoot\_length, weight 39 | - [plots.csv](https://ndownloader.figshare.com/files/3299474) - information on plot number and type 40 | Fields: plot\_id, plot\_type 41 | - [species.csv](https://ndownloader.figshare.com/files/3299483) - information on species codes and scientific name 42 | Fields: species\_id, genus, species, taxa 43 | - [portal\_mammals.sqlite](https://ndownloader.figshare.com/files/2292171) - database of survey, plots and species tables 44 | 45 | 46 | -------------------------------------------------------------------------------- /learners/discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Discussion 3 | --- 4 | 5 | FIXME 6 | 7 | 8 | -------------------------------------------------------------------------------- /learners/reference.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Glossary' 3 | --- 4 | 5 | ## Glossary 6 | 7 | FIXME 8 | 9 | 10 | -------------------------------------------------------------------------------- /learners/setup.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setup 3 | --- 4 | 5 | ```{r include-setup-overview, child="files/setup-overview.md"} 6 | ``` 7 | 8 | ## Setup instructions for your workshop 9 | 10 | - If you are attending a workshop where Python will be taught, 11 | follow [these setup instructions](setup-python-workshop.md) 12 | 13 | - If you are attending a workshop where R will be taught, 14 | follow [these setup instructions](setup-r-workshop.md) 15 | 16 | 17 | -------------------------------------------------------------------------------- /profiles/learner-profiles.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: FIXME 3 | --- 4 | 5 | This is a placeholder file. Please add content here. 6 | -------------------------------------------------------------------------------- /renv/activate.R: -------------------------------------------------------------------------------- 1 | 2 | local({ 3 | 4 | # the requested version of renv 5 | version <- "1.1.4" 6 | attr(version, "sha") <- NULL 7 | 8 | # the project directory 9 | project <- Sys.getenv("RENV_PROJECT") 10 | if (!nzchar(project)) 11 | project <- getwd() 12 | 13 | # use start-up diagnostics if enabled 14 | diagnostics <- Sys.getenv("RENV_STARTUP_DIAGNOSTICS", unset = "FALSE") 15 | if (diagnostics) { 16 | start <- Sys.time() 17 | profile <- tempfile("renv-startup-", fileext = ".Rprof") 18 | utils::Rprof(profile) 19 | on.exit({ 20 | utils::Rprof(NULL) 21 | elapsed <- signif(difftime(Sys.time(), start, units = "auto"), digits = 2L) 22 | writeLines(sprintf("- renv took %s to run the autoloader.", format(elapsed))) 23 | writeLines(sprintf("- Profile: %s", profile)) 24 | print(utils::summaryRprof(profile)) 25 | }, add = TRUE) 26 | } 27 | 28 | # figure out whether the autoloader is enabled 29 | enabled <- local({ 30 | 31 | # first, check config option 32 | override <- getOption("renv.config.autoloader.enabled") 33 | if (!is.null(override)) 34 | return(override) 35 | 36 | # if we're being run in a context where R_LIBS is already set, 37 | # don't load -- presumably we're being run as a sub-process and 38 | # the parent process has already set up library paths for us 39 | rcmd <- Sys.getenv("R_CMD", unset = NA) 40 | rlibs <- Sys.getenv("R_LIBS", unset = NA) 41 | if (!is.na(rlibs) && !is.na(rcmd)) 42 | return(FALSE) 43 | 44 | # next, check environment variables 45 | # prefer using the configuration one in the future 46 | envvars <- c( 47 | "RENV_CONFIG_AUTOLOADER_ENABLED", 48 | "RENV_AUTOLOADER_ENABLED", 49 | "RENV_ACTIVATE_PROJECT" 50 | ) 51 | 52 | for (envvar in envvars) { 53 | envval <- Sys.getenv(envvar, unset = NA) 54 | if (!is.na(envval)) 55 | return(tolower(envval) %in% c("true", "t", "1")) 56 | } 57 | 58 | # enable by default 59 | TRUE 60 | 61 | }) 62 | 63 | # bail if we're not enabled 64 | if (!enabled) { 65 | 66 | # if we're not enabled, we might still need to manually load 67 | # the user profile here 68 | profile <- Sys.getenv("R_PROFILE_USER", unset = "~/.Rprofile") 69 | if (file.exists(profile)) { 70 | cfg <- Sys.getenv("RENV_CONFIG_USER_PROFILE", unset = "TRUE") 71 | if (tolower(cfg) %in% c("true", "t", "1")) 72 | sys.source(profile, envir = globalenv()) 73 | } 74 | 75 | return(FALSE) 76 | 77 | } 78 | 79 | # avoid recursion 80 | if (identical(getOption("renv.autoloader.running"), TRUE)) { 81 | warning("ignoring recursive attempt to run renv autoloader") 82 | return(invisible(TRUE)) 83 | } 84 | 85 | # signal that we're loading renv during R startup 86 | options(renv.autoloader.running = TRUE) 87 | on.exit(options(renv.autoloader.running = NULL), add = TRUE) 88 | 89 | # signal that we've consented to use renv 90 | options(renv.consent = TRUE) 91 | 92 | # load the 'utils' package eagerly -- this ensures that renv shims, which 93 | # mask 'utils' packages, will come first on the search path 94 | library(utils, lib.loc = .Library) 95 | 96 | # unload renv if it's already been loaded 97 | if ("renv" %in% loadedNamespaces()) 98 | unloadNamespace("renv") 99 | 100 | # load bootstrap tools 101 | ansify <- function(text) { 102 | if (renv_ansify_enabled()) 103 | renv_ansify_enhanced(text) 104 | else 105 | renv_ansify_default(text) 106 | } 107 | 108 | renv_ansify_enabled <- function() { 109 | 110 | override <- Sys.getenv("RENV_ANSIFY_ENABLED", unset = NA) 111 | if (!is.na(override)) 112 | return(as.logical(override)) 113 | 114 | pane <- Sys.getenv("RSTUDIO_CHILD_PROCESS_PANE", unset = NA) 115 | if (identical(pane, "build")) 116 | return(FALSE) 117 | 118 | testthat <- Sys.getenv("TESTTHAT", unset = "false") 119 | if (tolower(testthat) %in% "true") 120 | return(FALSE) 121 | 122 | iderun <- Sys.getenv("R_CLI_HAS_HYPERLINK_IDE_RUN", unset = "false") 123 | if (tolower(iderun) %in% "false") 124 | return(FALSE) 125 | 126 | TRUE 127 | 128 | } 129 | 130 | renv_ansify_default <- function(text) { 131 | text 132 | } 133 | 134 | renv_ansify_enhanced <- function(text) { 135 | 136 | # R help links 137 | pattern <- "`\\?(renv::(?:[^`])+)`" 138 | replacement <- "`\033]8;;x-r-help:\\1\a?\\1\033]8;;\a`" 139 | text <- gsub(pattern, replacement, text, perl = TRUE) 140 | 141 | # runnable code 142 | pattern <- "`(renv::(?:[^`])+)`" 143 | replacement <- "`\033]8;;x-r-run:\\1\a\\1\033]8;;\a`" 144 | text <- gsub(pattern, replacement, text, perl = TRUE) 145 | 146 | # return ansified text 147 | text 148 | 149 | } 150 | 151 | renv_ansify_init <- function() { 152 | 153 | envir <- renv_envir_self() 154 | if (renv_ansify_enabled()) 155 | assign("ansify", renv_ansify_enhanced, envir = envir) 156 | else 157 | assign("ansify", renv_ansify_default, envir = envir) 158 | 159 | } 160 | 161 | `%||%` <- function(x, y) { 162 | if (is.null(x)) y else x 163 | } 164 | 165 | catf <- function(fmt, ..., appendLF = TRUE) { 166 | 167 | quiet <- getOption("renv.bootstrap.quiet", default = FALSE) 168 | if (quiet) 169 | return(invisible()) 170 | 171 | msg <- sprintf(fmt, ...) 172 | cat(msg, file = stdout(), sep = if (appendLF) "\n" else "") 173 | 174 | invisible(msg) 175 | 176 | } 177 | 178 | header <- function(label, 179 | ..., 180 | prefix = "#", 181 | suffix = "-", 182 | n = min(getOption("width"), 78)) 183 | { 184 | label <- sprintf(label, ...) 185 | n <- max(n - nchar(label) - nchar(prefix) - 2L, 8L) 186 | if (n <= 0) 187 | return(paste(prefix, label)) 188 | 189 | tail <- paste(rep.int(suffix, n), collapse = "") 190 | paste0(prefix, " ", label, " ", tail) 191 | 192 | } 193 | 194 | heredoc <- function(text, leave = 0) { 195 | 196 | # remove leading, trailing whitespace 197 | trimmed <- gsub("^\\s*\\n|\\n\\s*$", "", text) 198 | 199 | # split into lines 200 | lines <- strsplit(trimmed, "\n", fixed = TRUE)[[1L]] 201 | 202 | # compute common indent 203 | indent <- regexpr("[^[:space:]]", lines) 204 | common <- min(setdiff(indent, -1L)) - leave 205 | text <- paste(substring(lines, common), collapse = "\n") 206 | 207 | # substitute in ANSI links for executable renv code 208 | ansify(text) 209 | 210 | } 211 | 212 | bootstrap <- function(version, library) { 213 | 214 | friendly <- renv_bootstrap_version_friendly(version) 215 | section <- header(sprintf("Bootstrapping renv %s", friendly)) 216 | catf(section) 217 | 218 | # attempt to download renv 219 | catf("- Downloading renv ... ", appendLF = FALSE) 220 | withCallingHandlers( 221 | tarball <- renv_bootstrap_download(version), 222 | error = function(err) { 223 | catf("FAILED") 224 | stop("failed to download:\n", conditionMessage(err)) 225 | } 226 | ) 227 | catf("OK") 228 | on.exit(unlink(tarball), add = TRUE) 229 | 230 | # now attempt to install 231 | catf("- Installing renv ... ", appendLF = FALSE) 232 | withCallingHandlers( 233 | status <- renv_bootstrap_install(version, tarball, library), 234 | error = function(err) { 235 | catf("FAILED") 236 | stop("failed to install:\n", conditionMessage(err)) 237 | } 238 | ) 239 | catf("OK") 240 | 241 | # add empty line to break up bootstrapping from normal output 242 | catf("") 243 | 244 | return(invisible()) 245 | } 246 | 247 | renv_bootstrap_tests_running <- function() { 248 | getOption("renv.tests.running", default = FALSE) 249 | } 250 | 251 | renv_bootstrap_repos <- function() { 252 | 253 | # get CRAN repository 254 | cran <- getOption("renv.repos.cran", "https://cloud.r-project.org") 255 | 256 | # check for repos override 257 | repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA) 258 | if (!is.na(repos)) { 259 | 260 | # check for RSPM; if set, use a fallback repository for renv 261 | rspm <- Sys.getenv("RSPM", unset = NA) 262 | if (identical(rspm, repos)) 263 | repos <- c(RSPM = rspm, CRAN = cran) 264 | 265 | return(repos) 266 | 267 | } 268 | 269 | # check for lockfile repositories 270 | repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity) 271 | if (!inherits(repos, "error") && length(repos)) 272 | return(repos) 273 | 274 | # retrieve current repos 275 | repos <- getOption("repos") 276 | 277 | # ensure @CRAN@ entries are resolved 278 | repos[repos == "@CRAN@"] <- cran 279 | 280 | # add in renv.bootstrap.repos if set 281 | default <- c(FALLBACK = "https://cloud.r-project.org") 282 | extra <- getOption("renv.bootstrap.repos", default = default) 283 | repos <- c(repos, extra) 284 | 285 | # remove duplicates that might've snuck in 286 | dupes <- duplicated(repos) | duplicated(names(repos)) 287 | repos[!dupes] 288 | 289 | } 290 | 291 | renv_bootstrap_repos_lockfile <- function() { 292 | 293 | lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock") 294 | if (!file.exists(lockpath)) 295 | return(NULL) 296 | 297 | lockfile <- tryCatch(renv_json_read(lockpath), error = identity) 298 | if (inherits(lockfile, "error")) { 299 | warning(lockfile) 300 | return(NULL) 301 | } 302 | 303 | repos <- lockfile$R$Repositories 304 | if (length(repos) == 0) 305 | return(NULL) 306 | 307 | keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1)) 308 | vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1)) 309 | names(vals) <- keys 310 | 311 | return(vals) 312 | 313 | } 314 | 315 | renv_bootstrap_download <- function(version) { 316 | 317 | sha <- attr(version, "sha", exact = TRUE) 318 | 319 | methods <- if (!is.null(sha)) { 320 | 321 | # attempting to bootstrap a development version of renv 322 | c( 323 | function() renv_bootstrap_download_tarball(sha), 324 | function() renv_bootstrap_download_github(sha) 325 | ) 326 | 327 | } else { 328 | 329 | # attempting to bootstrap a release version of renv 330 | c( 331 | function() renv_bootstrap_download_tarball(version), 332 | function() renv_bootstrap_download_cran_latest(version), 333 | function() renv_bootstrap_download_cran_archive(version) 334 | ) 335 | 336 | } 337 | 338 | for (method in methods) { 339 | path <- tryCatch(method(), error = identity) 340 | if (is.character(path) && file.exists(path)) 341 | return(path) 342 | } 343 | 344 | stop("All download methods failed") 345 | 346 | } 347 | 348 | renv_bootstrap_download_impl <- function(url, destfile) { 349 | 350 | mode <- "wb" 351 | 352 | # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715 353 | fixup <- 354 | Sys.info()[["sysname"]] == "Windows" && 355 | substring(url, 1L, 5L) == "file:" 356 | 357 | if (fixup) 358 | mode <- "w+b" 359 | 360 | args <- list( 361 | url = url, 362 | destfile = destfile, 363 | mode = mode, 364 | quiet = TRUE 365 | ) 366 | 367 | if ("headers" %in% names(formals(utils::download.file))) { 368 | headers <- renv_bootstrap_download_custom_headers(url) 369 | if (length(headers) && is.character(headers)) 370 | args$headers <- headers 371 | } 372 | 373 | do.call(utils::download.file, args) 374 | 375 | } 376 | 377 | renv_bootstrap_download_custom_headers <- function(url) { 378 | 379 | headers <- getOption("renv.download.headers") 380 | if (is.null(headers)) 381 | return(character()) 382 | 383 | if (!is.function(headers)) 384 | stopf("'renv.download.headers' is not a function") 385 | 386 | headers <- headers(url) 387 | if (length(headers) == 0L) 388 | return(character()) 389 | 390 | if (is.list(headers)) 391 | headers <- unlist(headers, recursive = FALSE, use.names = TRUE) 392 | 393 | ok <- 394 | is.character(headers) && 395 | is.character(names(headers)) && 396 | all(nzchar(names(headers))) 397 | 398 | if (!ok) 399 | stop("invocation of 'renv.download.headers' did not return a named character vector") 400 | 401 | headers 402 | 403 | } 404 | 405 | renv_bootstrap_download_cran_latest <- function(version) { 406 | 407 | spec <- renv_bootstrap_download_cran_latest_find(version) 408 | type <- spec$type 409 | repos <- spec$repos 410 | 411 | baseurl <- utils::contrib.url(repos = repos, type = type) 412 | ext <- if (identical(type, "source")) 413 | ".tar.gz" 414 | else if (Sys.info()[["sysname"]] == "Windows") 415 | ".zip" 416 | else 417 | ".tgz" 418 | name <- sprintf("renv_%s%s", version, ext) 419 | url <- paste(baseurl, name, sep = "/") 420 | 421 | destfile <- file.path(tempdir(), name) 422 | status <- tryCatch( 423 | renv_bootstrap_download_impl(url, destfile), 424 | condition = identity 425 | ) 426 | 427 | if (inherits(status, "condition")) 428 | return(FALSE) 429 | 430 | # report success and return 431 | destfile 432 | 433 | } 434 | 435 | renv_bootstrap_download_cran_latest_find <- function(version) { 436 | 437 | # check whether binaries are supported on this system 438 | binary <- 439 | getOption("renv.bootstrap.binary", default = TRUE) && 440 | !identical(.Platform$pkgType, "source") && 441 | !identical(getOption("pkgType"), "source") && 442 | Sys.info()[["sysname"]] %in% c("Darwin", "Windows") 443 | 444 | types <- c(if (binary) "binary", "source") 445 | 446 | # iterate over types + repositories 447 | for (type in types) { 448 | for (repos in renv_bootstrap_repos()) { 449 | 450 | # build arguments for utils::available.packages() call 451 | args <- list(type = type, repos = repos) 452 | 453 | # add custom headers if available -- note that 454 | # utils::available.packages() will pass this to download.file() 455 | if ("headers" %in% names(formals(utils::download.file))) { 456 | headers <- renv_bootstrap_download_custom_headers(repos) 457 | if (length(headers) && is.character(headers)) 458 | args$headers <- headers 459 | } 460 | 461 | # retrieve package database 462 | db <- tryCatch( 463 | as.data.frame( 464 | do.call(utils::available.packages, args), 465 | stringsAsFactors = FALSE 466 | ), 467 | error = identity 468 | ) 469 | 470 | if (inherits(db, "error")) 471 | next 472 | 473 | # check for compatible entry 474 | entry <- db[db$Package %in% "renv" & db$Version %in% version, ] 475 | if (nrow(entry) == 0) 476 | next 477 | 478 | # found it; return spec to caller 479 | spec <- list(entry = entry, type = type, repos = repos) 480 | return(spec) 481 | 482 | } 483 | } 484 | 485 | # if we got here, we failed to find renv 486 | fmt <- "renv %s is not available from your declared package repositories" 487 | stop(sprintf(fmt, version)) 488 | 489 | } 490 | 491 | renv_bootstrap_download_cran_archive <- function(version) { 492 | 493 | name <- sprintf("renv_%s.tar.gz", version) 494 | repos <- renv_bootstrap_repos() 495 | urls <- file.path(repos, "src/contrib/Archive/renv", name) 496 | destfile <- file.path(tempdir(), name) 497 | 498 | for (url in urls) { 499 | 500 | status <- tryCatch( 501 | renv_bootstrap_download_impl(url, destfile), 502 | condition = identity 503 | ) 504 | 505 | if (identical(status, 0L)) 506 | return(destfile) 507 | 508 | } 509 | 510 | return(FALSE) 511 | 512 | } 513 | 514 | renv_bootstrap_download_tarball <- function(version) { 515 | 516 | # if the user has provided the path to a tarball via 517 | # an environment variable, then use it 518 | tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA) 519 | if (is.na(tarball)) 520 | return() 521 | 522 | # allow directories 523 | if (dir.exists(tarball)) { 524 | name <- sprintf("renv_%s.tar.gz", version) 525 | tarball <- file.path(tarball, name) 526 | } 527 | 528 | # bail if it doesn't exist 529 | if (!file.exists(tarball)) { 530 | 531 | # let the user know we weren't able to honour their request 532 | fmt <- "- RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist." 533 | msg <- sprintf(fmt, tarball) 534 | warning(msg) 535 | 536 | # bail 537 | return() 538 | 539 | } 540 | 541 | catf("- Using local tarball '%s'.", tarball) 542 | tarball 543 | 544 | } 545 | 546 | renv_bootstrap_github_token <- function() { 547 | for (envvar in c("GITHUB_TOKEN", "GITHUB_PAT", "GH_TOKEN")) { 548 | envval <- Sys.getenv(envvar, unset = NA) 549 | if (!is.na(envval)) 550 | return(envval) 551 | } 552 | } 553 | 554 | renv_bootstrap_download_github <- function(version) { 555 | 556 | enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE") 557 | if (!identical(enabled, "TRUE")) 558 | return(FALSE) 559 | 560 | # prepare download options 561 | token <- renv_bootstrap_github_token() 562 | if (is.null(token)) 563 | token <- "" 564 | 565 | if (nzchar(Sys.which("curl")) && nzchar(token)) { 566 | fmt <- "--location --fail --header \"Authorization: token %s\"" 567 | extra <- sprintf(fmt, token) 568 | saved <- options("download.file.method", "download.file.extra") 569 | options(download.file.method = "curl", download.file.extra = extra) 570 | on.exit(do.call(base::options, saved), add = TRUE) 571 | } else if (nzchar(Sys.which("wget")) && nzchar(token)) { 572 | fmt <- "--header=\"Authorization: token %s\"" 573 | extra <- sprintf(fmt, token) 574 | saved <- options("download.file.method", "download.file.extra") 575 | options(download.file.method = "wget", download.file.extra = extra) 576 | on.exit(do.call(base::options, saved), add = TRUE) 577 | } 578 | 579 | url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version) 580 | name <- sprintf("renv_%s.tar.gz", version) 581 | destfile <- file.path(tempdir(), name) 582 | 583 | status <- tryCatch( 584 | renv_bootstrap_download_impl(url, destfile), 585 | condition = identity 586 | ) 587 | 588 | if (!identical(status, 0L)) 589 | return(FALSE) 590 | 591 | renv_bootstrap_download_augment(destfile) 592 | 593 | return(destfile) 594 | 595 | } 596 | 597 | # Add Sha to DESCRIPTION. This is stop gap until #890, after which we 598 | # can use renv::install() to fully capture metadata. 599 | renv_bootstrap_download_augment <- function(destfile) { 600 | sha <- renv_bootstrap_git_extract_sha1_tar(destfile) 601 | if (is.null(sha)) { 602 | return() 603 | } 604 | 605 | # Untar 606 | tempdir <- tempfile("renv-github-") 607 | on.exit(unlink(tempdir, recursive = TRUE), add = TRUE) 608 | untar(destfile, exdir = tempdir) 609 | pkgdir <- dir(tempdir, full.names = TRUE)[[1]] 610 | 611 | # Modify description 612 | desc_path <- file.path(pkgdir, "DESCRIPTION") 613 | desc_lines <- readLines(desc_path) 614 | remotes_fields <- c( 615 | "RemoteType: github", 616 | "RemoteHost: api.github.com", 617 | "RemoteRepo: renv", 618 | "RemoteUsername: rstudio", 619 | "RemotePkgRef: rstudio/renv", 620 | paste("RemoteRef: ", sha), 621 | paste("RemoteSha: ", sha) 622 | ) 623 | writeLines(c(desc_lines[desc_lines != ""], remotes_fields), con = desc_path) 624 | 625 | # Re-tar 626 | local({ 627 | old <- setwd(tempdir) 628 | on.exit(setwd(old), add = TRUE) 629 | 630 | tar(destfile, compression = "gzip") 631 | }) 632 | invisible() 633 | } 634 | 635 | # Extract the commit hash from a git archive. Git archives include the SHA1 636 | # hash as the comment field of the tarball pax extended header 637 | # (see https://www.kernel.org/pub/software/scm/git/docs/git-archive.html) 638 | # For GitHub archives this should be the first header after the default one 639 | # (512 byte) header. 640 | renv_bootstrap_git_extract_sha1_tar <- function(bundle) { 641 | 642 | # open the bundle for reading 643 | # We use gzcon for everything because (from ?gzcon) 644 | # > Reading from a connection which does not supply a 'gzip' magic 645 | # > header is equivalent to reading from the original connection 646 | conn <- gzcon(file(bundle, open = "rb", raw = TRUE)) 647 | on.exit(close(conn)) 648 | 649 | # The default pax header is 512 bytes long and the first pax extended header 650 | # with the comment should be 51 bytes long 651 | # `52 comment=` (11 chars) + 40 byte SHA1 hash 652 | len <- 0x200 + 0x33 653 | res <- rawToChar(readBin(conn, "raw", n = len)[0x201:len]) 654 | 655 | if (grepl("^52 comment=", res)) { 656 | sub("52 comment=", "", res) 657 | } else { 658 | NULL 659 | } 660 | } 661 | 662 | renv_bootstrap_install <- function(version, tarball, library) { 663 | 664 | # attempt to install it into project library 665 | dir.create(library, showWarnings = FALSE, recursive = TRUE) 666 | output <- renv_bootstrap_install_impl(library, tarball) 667 | 668 | # check for successful install 669 | status <- attr(output, "status") 670 | if (is.null(status) || identical(status, 0L)) 671 | return(status) 672 | 673 | # an error occurred; report it 674 | header <- "installation of renv failed" 675 | lines <- paste(rep.int("=", nchar(header)), collapse = "") 676 | text <- paste(c(header, lines, output), collapse = "\n") 677 | stop(text) 678 | 679 | } 680 | 681 | renv_bootstrap_install_impl <- function(library, tarball) { 682 | 683 | # invoke using system2 so we can capture and report output 684 | bin <- R.home("bin") 685 | exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R" 686 | R <- file.path(bin, exe) 687 | 688 | args <- c( 689 | "--vanilla", "CMD", "INSTALL", "--no-multiarch", 690 | "-l", shQuote(path.expand(library)), 691 | shQuote(path.expand(tarball)) 692 | ) 693 | 694 | system2(R, args, stdout = TRUE, stderr = TRUE) 695 | 696 | } 697 | 698 | renv_bootstrap_platform_prefix_default <- function() { 699 | 700 | # read version component 701 | version <- Sys.getenv("RENV_PATHS_VERSION", unset = "R-%v") 702 | 703 | # expand placeholders 704 | placeholders <- list( 705 | list("%v", format(getRversion()[1, 1:2])), 706 | list("%V", format(getRversion()[1, 1:3])) 707 | ) 708 | 709 | for (placeholder in placeholders) 710 | version <- gsub(placeholder[[1L]], placeholder[[2L]], version, fixed = TRUE) 711 | 712 | # include SVN revision for development versions of R 713 | # (to avoid sharing platform-specific artefacts with released versions of R) 714 | devel <- 715 | identical(R.version[["status"]], "Under development (unstable)") || 716 | identical(R.version[["nickname"]], "Unsuffered Consequences") 717 | 718 | if (devel) 719 | version <- paste(version, R.version[["svn rev"]], sep = "-r") 720 | 721 | version 722 | 723 | } 724 | 725 | renv_bootstrap_platform_prefix <- function() { 726 | 727 | # construct version prefix 728 | version <- renv_bootstrap_platform_prefix_default() 729 | 730 | # build list of path components 731 | components <- c(version, R.version$platform) 732 | 733 | # include prefix if provided by user 734 | prefix <- renv_bootstrap_platform_prefix_impl() 735 | if (!is.na(prefix) && nzchar(prefix)) 736 | components <- c(prefix, components) 737 | 738 | # build prefix 739 | paste(components, collapse = "/") 740 | 741 | } 742 | 743 | renv_bootstrap_platform_prefix_impl <- function() { 744 | 745 | # if an explicit prefix has been supplied, use it 746 | prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA) 747 | if (!is.na(prefix)) 748 | return(prefix) 749 | 750 | # if the user has requested an automatic prefix, generate it 751 | auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA) 752 | if (is.na(auto) && getRversion() >= "4.4.0") 753 | auto <- "TRUE" 754 | 755 | if (auto %in% c("TRUE", "True", "true", "1")) 756 | return(renv_bootstrap_platform_prefix_auto()) 757 | 758 | # empty string on failure 759 | "" 760 | 761 | } 762 | 763 | renv_bootstrap_platform_prefix_auto <- function() { 764 | 765 | prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity) 766 | if (inherits(prefix, "error") || prefix %in% "unknown") { 767 | 768 | msg <- paste( 769 | "failed to infer current operating system", 770 | "please file a bug report at https://github.com/rstudio/renv/issues", 771 | sep = "; " 772 | ) 773 | 774 | warning(msg) 775 | 776 | } 777 | 778 | prefix 779 | 780 | } 781 | 782 | renv_bootstrap_platform_os <- function() { 783 | 784 | sysinfo <- Sys.info() 785 | sysname <- sysinfo[["sysname"]] 786 | 787 | # handle Windows + macOS up front 788 | if (sysname == "Windows") 789 | return("windows") 790 | else if (sysname == "Darwin") 791 | return("macos") 792 | 793 | # check for os-release files 794 | for (file in c("/etc/os-release", "/usr/lib/os-release")) 795 | if (file.exists(file)) 796 | return(renv_bootstrap_platform_os_via_os_release(file, sysinfo)) 797 | 798 | # check for redhat-release files 799 | if (file.exists("/etc/redhat-release")) 800 | return(renv_bootstrap_platform_os_via_redhat_release()) 801 | 802 | "unknown" 803 | 804 | } 805 | 806 | renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) { 807 | 808 | # read /etc/os-release 809 | release <- utils::read.table( 810 | file = file, 811 | sep = "=", 812 | quote = c("\"", "'"), 813 | col.names = c("Key", "Value"), 814 | comment.char = "#", 815 | stringsAsFactors = FALSE 816 | ) 817 | 818 | vars <- as.list(release$Value) 819 | names(vars) <- release$Key 820 | 821 | # get os name 822 | os <- tolower(sysinfo[["sysname"]]) 823 | 824 | # read id 825 | id <- "unknown" 826 | for (field in c("ID", "ID_LIKE")) { 827 | if (field %in% names(vars) && nzchar(vars[[field]])) { 828 | id <- vars[[field]] 829 | break 830 | } 831 | } 832 | 833 | # read version 834 | version <- "unknown" 835 | for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) { 836 | if (field %in% names(vars) && nzchar(vars[[field]])) { 837 | version <- vars[[field]] 838 | break 839 | } 840 | } 841 | 842 | # join together 843 | paste(c(os, id, version), collapse = "-") 844 | 845 | } 846 | 847 | renv_bootstrap_platform_os_via_redhat_release <- function() { 848 | 849 | # read /etc/redhat-release 850 | contents <- readLines("/etc/redhat-release", warn = FALSE) 851 | 852 | # infer id 853 | id <- if (grepl("centos", contents, ignore.case = TRUE)) 854 | "centos" 855 | else if (grepl("redhat", contents, ignore.case = TRUE)) 856 | "redhat" 857 | else 858 | "unknown" 859 | 860 | # try to find a version component (very hacky) 861 | version <- "unknown" 862 | 863 | parts <- strsplit(contents, "[[:space:]]")[[1L]] 864 | for (part in parts) { 865 | 866 | nv <- tryCatch(numeric_version(part), error = identity) 867 | if (inherits(nv, "error")) 868 | next 869 | 870 | version <- nv[1, 1] 871 | break 872 | 873 | } 874 | 875 | paste(c("linux", id, version), collapse = "-") 876 | 877 | } 878 | 879 | renv_bootstrap_library_root_name <- function(project) { 880 | 881 | # use project name as-is if requested 882 | asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE") 883 | if (asis) 884 | return(basename(project)) 885 | 886 | # otherwise, disambiguate based on project's path 887 | id <- substring(renv_bootstrap_hash_text(project), 1L, 8L) 888 | paste(basename(project), id, sep = "-") 889 | 890 | } 891 | 892 | renv_bootstrap_library_root <- function(project) { 893 | 894 | prefix <- renv_bootstrap_profile_prefix() 895 | 896 | path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA) 897 | if (!is.na(path)) 898 | return(paste(c(path, prefix), collapse = "/")) 899 | 900 | path <- renv_bootstrap_library_root_impl(project) 901 | if (!is.null(path)) { 902 | name <- renv_bootstrap_library_root_name(project) 903 | return(paste(c(path, prefix, name), collapse = "/")) 904 | } 905 | 906 | renv_bootstrap_paths_renv("library", project = project) 907 | 908 | } 909 | 910 | renv_bootstrap_library_root_impl <- function(project) { 911 | 912 | root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA) 913 | if (!is.na(root)) 914 | return(root) 915 | 916 | type <- renv_bootstrap_project_type(project) 917 | if (identical(type, "package")) { 918 | userdir <- renv_bootstrap_user_dir() 919 | return(file.path(userdir, "library")) 920 | } 921 | 922 | } 923 | 924 | renv_bootstrap_validate_version <- function(version, description = NULL) { 925 | 926 | # resolve description file 927 | # 928 | # avoid passing lib.loc to `packageDescription()` below, since R will 929 | # use the loaded version of the package by default anyhow. note that 930 | # this function should only be called after 'renv' is loaded 931 | # https://github.com/rstudio/renv/issues/1625 932 | description <- description %||% packageDescription("renv") 933 | 934 | # check whether requested version 'version' matches loaded version of renv 935 | sha <- attr(version, "sha", exact = TRUE) 936 | valid <- if (!is.null(sha)) 937 | renv_bootstrap_validate_version_dev(sha, description) 938 | else 939 | renv_bootstrap_validate_version_release(version, description) 940 | 941 | if (valid) 942 | return(TRUE) 943 | 944 | # the loaded version of renv doesn't match the requested version; 945 | # give the user instructions on how to proceed 946 | dev <- identical(description[["RemoteType"]], "github") 947 | remote <- if (dev) 948 | paste("rstudio/renv", description[["RemoteSha"]], sep = "@") 949 | else 950 | paste("renv", description[["Version"]], sep = "@") 951 | 952 | # display both loaded version + sha if available 953 | friendly <- renv_bootstrap_version_friendly( 954 | version = description[["Version"]], 955 | sha = if (dev) description[["RemoteSha"]] 956 | ) 957 | 958 | fmt <- heredoc(" 959 | renv %1$s was loaded from project library, but this project is configured to use renv %2$s. 960 | - Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile. 961 | - Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library. 962 | ") 963 | catf(fmt, friendly, renv_bootstrap_version_friendly(version), remote) 964 | 965 | FALSE 966 | 967 | } 968 | 969 | renv_bootstrap_validate_version_dev <- function(version, description) { 970 | 971 | expected <- description[["RemoteSha"]] 972 | if (!is.character(expected)) 973 | return(FALSE) 974 | 975 | pattern <- sprintf("^\\Q%s\\E", version) 976 | grepl(pattern, expected, perl = TRUE) 977 | 978 | } 979 | 980 | renv_bootstrap_validate_version_release <- function(version, description) { 981 | expected <- description[["Version"]] 982 | is.character(expected) && identical(expected, version) 983 | } 984 | 985 | renv_bootstrap_hash_text <- function(text) { 986 | 987 | hashfile <- tempfile("renv-hash-") 988 | on.exit(unlink(hashfile), add = TRUE) 989 | 990 | writeLines(text, con = hashfile) 991 | tools::md5sum(hashfile) 992 | 993 | } 994 | 995 | renv_bootstrap_load <- function(project, libpath, version) { 996 | 997 | # try to load renv from the project library 998 | if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) 999 | return(FALSE) 1000 | 1001 | # warn if the version of renv loaded does not match 1002 | renv_bootstrap_validate_version(version) 1003 | 1004 | # execute renv load hooks, if any 1005 | hooks <- getHook("renv::autoload") 1006 | for (hook in hooks) 1007 | if (is.function(hook)) 1008 | tryCatch(hook(), error = warnify) 1009 | 1010 | # load the project 1011 | renv::load(project) 1012 | 1013 | TRUE 1014 | 1015 | } 1016 | 1017 | renv_bootstrap_profile_load <- function(project) { 1018 | 1019 | # if RENV_PROFILE is already set, just use that 1020 | profile <- Sys.getenv("RENV_PROFILE", unset = NA) 1021 | if (!is.na(profile) && nzchar(profile)) 1022 | return(profile) 1023 | 1024 | # check for a profile file (nothing to do if it doesn't exist) 1025 | path <- renv_bootstrap_paths_renv("profile", profile = FALSE, project = project) 1026 | if (!file.exists(path)) 1027 | return(NULL) 1028 | 1029 | # read the profile, and set it if it exists 1030 | contents <- readLines(path, warn = FALSE) 1031 | if (length(contents) == 0L) 1032 | return(NULL) 1033 | 1034 | # set RENV_PROFILE 1035 | profile <- contents[[1L]] 1036 | if (!profile %in% c("", "default")) 1037 | Sys.setenv(RENV_PROFILE = profile) 1038 | 1039 | profile 1040 | 1041 | } 1042 | 1043 | renv_bootstrap_profile_prefix <- function() { 1044 | profile <- renv_bootstrap_profile_get() 1045 | if (!is.null(profile)) 1046 | return(file.path("profiles", profile, "renv")) 1047 | } 1048 | 1049 | renv_bootstrap_profile_get <- function() { 1050 | profile <- Sys.getenv("RENV_PROFILE", unset = "") 1051 | renv_bootstrap_profile_normalize(profile) 1052 | } 1053 | 1054 | renv_bootstrap_profile_set <- function(profile) { 1055 | profile <- renv_bootstrap_profile_normalize(profile) 1056 | if (is.null(profile)) 1057 | Sys.unsetenv("RENV_PROFILE") 1058 | else 1059 | Sys.setenv(RENV_PROFILE = profile) 1060 | } 1061 | 1062 | renv_bootstrap_profile_normalize <- function(profile) { 1063 | 1064 | if (is.null(profile) || profile %in% c("", "default")) 1065 | return(NULL) 1066 | 1067 | profile 1068 | 1069 | } 1070 | 1071 | renv_bootstrap_path_absolute <- function(path) { 1072 | 1073 | substr(path, 1L, 1L) %in% c("~", "/", "\\") || ( 1074 | substr(path, 1L, 1L) %in% c(letters, LETTERS) && 1075 | substr(path, 2L, 3L) %in% c(":/", ":\\") 1076 | ) 1077 | 1078 | } 1079 | 1080 | renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) { 1081 | renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv") 1082 | root <- if (renv_bootstrap_path_absolute(renv)) NULL else project 1083 | prefix <- if (profile) renv_bootstrap_profile_prefix() 1084 | components <- c(root, renv, prefix, ...) 1085 | paste(components, collapse = "/") 1086 | } 1087 | 1088 | renv_bootstrap_project_type <- function(path) { 1089 | 1090 | descpath <- file.path(path, "DESCRIPTION") 1091 | if (!file.exists(descpath)) 1092 | return("unknown") 1093 | 1094 | desc <- tryCatch( 1095 | read.dcf(descpath, all = TRUE), 1096 | error = identity 1097 | ) 1098 | 1099 | if (inherits(desc, "error")) 1100 | return("unknown") 1101 | 1102 | type <- desc$Type 1103 | if (!is.null(type)) 1104 | return(tolower(type)) 1105 | 1106 | package <- desc$Package 1107 | if (!is.null(package)) 1108 | return("package") 1109 | 1110 | "unknown" 1111 | 1112 | } 1113 | 1114 | renv_bootstrap_user_dir <- function() { 1115 | dir <- renv_bootstrap_user_dir_impl() 1116 | path.expand(chartr("\\", "/", dir)) 1117 | } 1118 | 1119 | renv_bootstrap_user_dir_impl <- function() { 1120 | 1121 | # use local override if set 1122 | override <- getOption("renv.userdir.override") 1123 | if (!is.null(override)) 1124 | return(override) 1125 | 1126 | # use R_user_dir if available 1127 | tools <- asNamespace("tools") 1128 | if (is.function(tools$R_user_dir)) 1129 | return(tools$R_user_dir("renv", "cache")) 1130 | 1131 | # try using our own backfill for older versions of R 1132 | envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME") 1133 | for (envvar in envvars) { 1134 | root <- Sys.getenv(envvar, unset = NA) 1135 | if (!is.na(root)) 1136 | return(file.path(root, "R/renv")) 1137 | } 1138 | 1139 | # use platform-specific default fallbacks 1140 | if (Sys.info()[["sysname"]] == "Windows") 1141 | file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv") 1142 | else if (Sys.info()[["sysname"]] == "Darwin") 1143 | "~/Library/Caches/org.R-project.R/R/renv" 1144 | else 1145 | "~/.cache/R/renv" 1146 | 1147 | } 1148 | 1149 | renv_bootstrap_version_friendly <- function(version, shafmt = NULL, sha = NULL) { 1150 | sha <- sha %||% attr(version, "sha", exact = TRUE) 1151 | parts <- c(version, sprintf(shafmt %||% " [sha: %s]", substring(sha, 1L, 7L))) 1152 | paste(parts, collapse = "") 1153 | } 1154 | 1155 | renv_bootstrap_exec <- function(project, libpath, version) { 1156 | if (!renv_bootstrap_load(project, libpath, version)) 1157 | renv_bootstrap_run(project, libpath, version) 1158 | } 1159 | 1160 | renv_bootstrap_run <- function(project, libpath, version) { 1161 | 1162 | # perform bootstrap 1163 | bootstrap(version, libpath) 1164 | 1165 | # exit early if we're just testing bootstrap 1166 | if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA))) 1167 | return(TRUE) 1168 | 1169 | # try again to load 1170 | if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { 1171 | return(renv::load(project = project)) 1172 | } 1173 | 1174 | # failed to download or load renv; warn the user 1175 | msg <- c( 1176 | "Failed to find an renv installation: the project will not be loaded.", 1177 | "Use `renv::activate()` to re-initialize the project." 1178 | ) 1179 | 1180 | warning(paste(msg, collapse = "\n"), call. = FALSE) 1181 | 1182 | } 1183 | 1184 | renv_json_read <- function(file = NULL, text = NULL) { 1185 | 1186 | jlerr <- NULL 1187 | 1188 | # if jsonlite is loaded, use that instead 1189 | if ("jsonlite" %in% loadedNamespaces()) { 1190 | 1191 | json <- tryCatch(renv_json_read_jsonlite(file, text), error = identity) 1192 | if (!inherits(json, "error")) 1193 | return(json) 1194 | 1195 | jlerr <- json 1196 | 1197 | } 1198 | 1199 | # otherwise, fall back to the default JSON reader 1200 | json <- tryCatch(renv_json_read_default(file, text), error = identity) 1201 | if (!inherits(json, "error")) 1202 | return(json) 1203 | 1204 | # report an error 1205 | if (!is.null(jlerr)) 1206 | stop(jlerr) 1207 | else 1208 | stop(json) 1209 | 1210 | } 1211 | 1212 | renv_json_read_jsonlite <- function(file = NULL, text = NULL) { 1213 | text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") 1214 | jsonlite::fromJSON(txt = text, simplifyVector = FALSE) 1215 | } 1216 | 1217 | renv_json_read_patterns <- function() { 1218 | 1219 | list( 1220 | 1221 | # objects 1222 | list("{", "\t\n\tobject(\t\n\t", TRUE), 1223 | list("}", "\t\n\t)\t\n\t", TRUE), 1224 | 1225 | # arrays 1226 | list("[", "\t\n\tarray(\t\n\t", TRUE), 1227 | list("]", "\n\t\n)\n\t\n", TRUE), 1228 | 1229 | # maps 1230 | list(":", "\t\n\t=\t\n\t", TRUE), 1231 | 1232 | # newlines 1233 | list("\\u000a", "\n", FALSE) 1234 | 1235 | ) 1236 | 1237 | } 1238 | 1239 | renv_json_read_envir <- function() { 1240 | 1241 | envir <- new.env(parent = emptyenv()) 1242 | 1243 | envir[["+"]] <- `+` 1244 | envir[["-"]] <- `-` 1245 | 1246 | envir[["object"]] <- function(...) { 1247 | result <- list(...) 1248 | names(result) <- as.character(names(result)) 1249 | result 1250 | } 1251 | 1252 | envir[["array"]] <- list 1253 | 1254 | envir[["true"]] <- TRUE 1255 | envir[["false"]] <- FALSE 1256 | envir[["null"]] <- NULL 1257 | 1258 | envir 1259 | 1260 | } 1261 | 1262 | renv_json_read_remap <- function(object, patterns) { 1263 | 1264 | # repair names if necessary 1265 | if (!is.null(names(object))) { 1266 | 1267 | nms <- names(object) 1268 | for (pattern in patterns) 1269 | nms <- gsub(pattern[[2L]], pattern[[1L]], nms, fixed = TRUE) 1270 | names(object) <- nms 1271 | 1272 | } 1273 | 1274 | # repair strings if necessary 1275 | if (is.character(object)) { 1276 | for (pattern in patterns) 1277 | object <- gsub(pattern[[2L]], pattern[[1L]], object, fixed = TRUE) 1278 | } 1279 | 1280 | # recurse for other objects 1281 | if (is.recursive(object)) 1282 | for (i in seq_along(object)) 1283 | object[i] <- list(renv_json_read_remap(object[[i]], patterns)) 1284 | 1285 | # return remapped object 1286 | object 1287 | 1288 | } 1289 | 1290 | renv_json_read_default <- function(file = NULL, text = NULL) { 1291 | 1292 | # read json text 1293 | text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") 1294 | 1295 | # convert into something the R parser will understand 1296 | patterns <- renv_json_read_patterns() 1297 | transformed <- text 1298 | for (pattern in patterns) 1299 | transformed <- gsub(pattern[[1L]], pattern[[2L]], transformed, fixed = TRUE) 1300 | 1301 | # parse it 1302 | rfile <- tempfile("renv-json-", fileext = ".R") 1303 | on.exit(unlink(rfile), add = TRUE) 1304 | writeLines(transformed, con = rfile) 1305 | json <- parse(rfile, keep.source = FALSE, srcfile = NULL)[[1L]] 1306 | 1307 | # evaluate in safe environment 1308 | result <- eval(json, envir = renv_json_read_envir()) 1309 | 1310 | # fix up strings if necessary -- do so only with reversible patterns 1311 | patterns <- Filter(function(pattern) pattern[[3L]], patterns) 1312 | renv_json_read_remap(result, patterns) 1313 | 1314 | } 1315 | 1316 | 1317 | # load the renv profile, if any 1318 | renv_bootstrap_profile_load(project) 1319 | 1320 | # construct path to library root 1321 | root <- renv_bootstrap_library_root(project) 1322 | 1323 | # construct library prefix for platform 1324 | prefix <- renv_bootstrap_platform_prefix() 1325 | 1326 | # construct full libpath 1327 | libpath <- file.path(root, prefix) 1328 | 1329 | # run bootstrap code 1330 | renv_bootstrap_exec(project, libpath, version) 1331 | 1332 | invisible() 1333 | 1334 | }) 1335 | -------------------------------------------------------------------------------- /renv/profile: -------------------------------------------------------------------------------- 1 | lesson-requirements 2 | -------------------------------------------------------------------------------- /renv/profiles/lesson-requirements/renv.lock: -------------------------------------------------------------------------------- 1 | { 2 | "R": { 3 | "Version": "4.5.0", 4 | "Repositories": [ 5 | { 6 | "Name": "carpentries", 7 | "URL": "https://carpentries.r-universe.dev" 8 | }, 9 | { 10 | "Name": "carpentries_archive", 11 | "URL": "https://carpentries.github.io/drat" 12 | }, 13 | { 14 | "Name": "CRAN", 15 | "URL": "https://cran.rstudio.com" 16 | } 17 | ] 18 | }, 19 | "Packages": { 20 | "R6": { 21 | "Package": "R6", 22 | "Version": "2.6.1", 23 | "Source": "Repository", 24 | "Title": "Encapsulated Classes with Reference Semantics", 25 | "Authors@R": "c( person(\"Winston\", \"Chang\", , \"winston@posit.co\", role = c(\"aut\", \"cre\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", 26 | "Description": "Creates classes with reference semantics, similar to R's built-in reference classes. Compared to reference classes, R6 classes are simpler and lighter-weight, and they are not built on S4 classes so they do not require the methods package. These classes allow public and private members, and they support inheritance, even when the classes are defined in different packages.", 27 | "License": "MIT + file LICENSE", 28 | "URL": "https://r6.r-lib.org, https://github.com/r-lib/R6", 29 | "BugReports": "https://github.com/r-lib/R6/issues", 30 | "Depends": [ 31 | "R (>= 3.6)" 32 | ], 33 | "Suggests": [ 34 | "lobstr", 35 | "testthat (>= 3.0.0)" 36 | ], 37 | "Config/Needs/website": "tidyverse/tidytemplate, ggplot2, microbenchmark, scales", 38 | "Config/testthat/edition": "3", 39 | "Encoding": "UTF-8", 40 | "RoxygenNote": "7.3.2", 41 | "NeedsCompilation": "no", 42 | "Author": "Winston Chang [aut, cre], Posit Software, PBC [cph, fnd]", 43 | "Maintainer": "Winston Chang ", 44 | "Repository": "CRAN" 45 | }, 46 | "base64enc": { 47 | "Package": "base64enc", 48 | "Version": "0.1-3", 49 | "Source": "Repository", 50 | "Title": "Tools for base64 encoding", 51 | "Author": "Simon Urbanek ", 52 | "Maintainer": "Simon Urbanek ", 53 | "Depends": [ 54 | "R (>= 2.9.0)" 55 | ], 56 | "Enhances": [ 57 | "png" 58 | ], 59 | "Description": "This package provides tools for handling base64 encoding. It is more flexible than the orphaned base64 package.", 60 | "License": "GPL-2 | GPL-3", 61 | "URL": "http://www.rforge.net/base64enc", 62 | "NeedsCompilation": "yes", 63 | "Repository": "RSPM", 64 | "Encoding": "UTF-8" 65 | }, 66 | "bslib": { 67 | "Package": "bslib", 68 | "Version": "0.9.0", 69 | "Source": "Repository", 70 | "Title": "Custom 'Bootstrap' 'Sass' Themes for 'shiny' and 'rmarkdown'", 71 | "Authors@R": "c( person(\"Carson\", \"Sievert\", , \"carson@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-4958-2844\")), person(\"Joe\", \"Cheng\", , \"joe@posit.co\", role = \"aut\"), person(\"Garrick\", \"Aden-Buie\", , \"garrick@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0002-7111-0077\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")), person(, \"Bootstrap contributors\", role = \"ctb\", comment = \"Bootstrap library\"), person(, \"Twitter, Inc\", role = \"cph\", comment = \"Bootstrap library\"), person(\"Javi\", \"Aguilar\", role = c(\"ctb\", \"cph\"), comment = \"Bootstrap colorpicker library\"), person(\"Thomas\", \"Park\", role = c(\"ctb\", \"cph\"), comment = \"Bootswatch library\"), person(, \"PayPal\", role = c(\"ctb\", \"cph\"), comment = \"Bootstrap accessibility plugin\") )", 72 | "Description": "Simplifies custom 'CSS' styling of both 'shiny' and 'rmarkdown' via 'Bootstrap' 'Sass'. Supports 'Bootstrap' 3, 4 and 5 as well as their various 'Bootswatch' themes. An interactive widget is also provided for previewing themes in real time.", 73 | "License": "MIT + file LICENSE", 74 | "URL": "https://rstudio.github.io/bslib/, https://github.com/rstudio/bslib", 75 | "BugReports": "https://github.com/rstudio/bslib/issues", 76 | "Depends": [ 77 | "R (>= 2.10)" 78 | ], 79 | "Imports": [ 80 | "base64enc", 81 | "cachem", 82 | "fastmap (>= 1.1.1)", 83 | "grDevices", 84 | "htmltools (>= 0.5.8)", 85 | "jquerylib (>= 0.1.3)", 86 | "jsonlite", 87 | "lifecycle", 88 | "memoise (>= 2.0.1)", 89 | "mime", 90 | "rlang", 91 | "sass (>= 0.4.9)" 92 | ], 93 | "Suggests": [ 94 | "bsicons", 95 | "curl", 96 | "fontawesome", 97 | "future", 98 | "ggplot2", 99 | "knitr", 100 | "magrittr", 101 | "rappdirs", 102 | "rmarkdown (>= 2.7)", 103 | "shiny (> 1.8.1)", 104 | "testthat", 105 | "thematic", 106 | "tools", 107 | "utils", 108 | "withr", 109 | "yaml" 110 | ], 111 | "Config/Needs/deploy": "BH, chiflights22, colourpicker, commonmark, cpp11, cpsievert/chiflights22, cpsievert/histoslider, dplyr, DT, ggplot2, ggridges, gt, hexbin, histoslider, htmlwidgets, lattice, leaflet, lubridate, markdown, modelr, plotly, reactable, reshape2, rprojroot, rsconnect, rstudio/shiny, scales, styler, tibble", 112 | "Config/Needs/routine": "chromote, desc, renv", 113 | "Config/Needs/website": "brio, crosstalk, dplyr, DT, ggplot2, glue, htmlwidgets, leaflet, lorem, palmerpenguins, plotly, purrr, rprojroot, rstudio/htmltools, scales, stringr, tidyr, webshot2", 114 | "Config/testthat/edition": "3", 115 | "Config/testthat/parallel": "true", 116 | "Config/testthat/start-first": "zzzz-bs-sass, fonts, zzz-precompile, theme-*, rmd-*", 117 | "Encoding": "UTF-8", 118 | "RoxygenNote": "7.3.2", 119 | "Collate": "'accordion.R' 'breakpoints.R' 'bs-current-theme.R' 'bs-dependencies.R' 'bs-global.R' 'bs-remove.R' 'bs-theme-layers.R' 'bs-theme-preset-bootswatch.R' 'bs-theme-preset-brand.R' 'bs-theme-preset-builtin.R' 'bs-theme-preset.R' 'utils.R' 'bs-theme-preview.R' 'bs-theme-update.R' 'bs-theme.R' 'bslib-package.R' 'buttons.R' 'card.R' 'deprecated.R' 'files.R' 'fill.R' 'imports.R' 'input-dark-mode.R' 'input-switch.R' 'layout.R' 'nav-items.R' 'nav-update.R' 'navbar_options.R' 'navs-legacy.R' 'navs.R' 'onLoad.R' 'page.R' 'popover.R' 'precompiled.R' 'print.R' 'shiny-devmode.R' 'sidebar.R' 'staticimports.R' 'tooltip.R' 'utils-deps.R' 'utils-shiny.R' 'utils-tags.R' 'value-box.R' 'version-default.R' 'versions.R'", 120 | "NeedsCompilation": "no", 121 | "Author": "Carson Sievert [aut, cre] (), Joe Cheng [aut], Garrick Aden-Buie [aut] (), Posit Software, PBC [cph, fnd], Bootstrap contributors [ctb] (Bootstrap library), Twitter, Inc [cph] (Bootstrap library), Javi Aguilar [ctb, cph] (Bootstrap colorpicker library), Thomas Park [ctb, cph] (Bootswatch library), PayPal [ctb, cph] (Bootstrap accessibility plugin)", 122 | "Maintainer": "Carson Sievert ", 123 | "Repository": "CRAN" 124 | }, 125 | "cachem": { 126 | "Package": "cachem", 127 | "Version": "1.1.0", 128 | "Source": "Repository", 129 | "Title": "Cache R Objects with Automatic Pruning", 130 | "Description": "Key-value stores with automatic pruning. Caches can limit either their total size or the age of the oldest object (or both), automatically pruning objects to maintain the constraints.", 131 | "Authors@R": "c( person(\"Winston\", \"Chang\", , \"winston@posit.co\", c(\"aut\", \"cre\")), person(family = \"Posit Software, PBC\", role = c(\"cph\", \"fnd\")))", 132 | "License": "MIT + file LICENSE", 133 | "Encoding": "UTF-8", 134 | "ByteCompile": "true", 135 | "URL": "https://cachem.r-lib.org/, https://github.com/r-lib/cachem", 136 | "Imports": [ 137 | "rlang", 138 | "fastmap (>= 1.2.0)" 139 | ], 140 | "Suggests": [ 141 | "testthat" 142 | ], 143 | "RoxygenNote": "7.2.3", 144 | "Config/Needs/routine": "lobstr", 145 | "Config/Needs/website": "pkgdown", 146 | "NeedsCompilation": "yes", 147 | "Author": "Winston Chang [aut, cre], Posit Software, PBC [cph, fnd]", 148 | "Maintainer": "Winston Chang ", 149 | "Repository": "RSPM" 150 | }, 151 | "cli": { 152 | "Package": "cli", 153 | "Version": "3.6.5", 154 | "Source": "Repository", 155 | "Title": "Helpers for Developing Command Line Interfaces", 156 | "Authors@R": "c( person(\"Gábor\", \"Csárdi\", , \"gabor@posit.co\", role = c(\"aut\", \"cre\")), person(\"Hadley\", \"Wickham\", role = \"ctb\"), person(\"Kirill\", \"Müller\", role = \"ctb\"), person(\"Salim\", \"Brüggemann\", , \"salim-b@pm.me\", role = \"ctb\", comment = c(ORCID = \"0000-0002-5329-5987\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", 157 | "Description": "A suite of tools to build attractive command line interfaces ('CLIs'), from semantic elements: headings, lists, alerts, paragraphs, etc. Supports custom themes via a 'CSS'-like language. It also contains a number of lower level 'CLI' elements: rules, boxes, trees, and 'Unicode' symbols with 'ASCII' alternatives. It support ANSI colors and text styles as well.", 158 | "License": "MIT + file LICENSE", 159 | "URL": "https://cli.r-lib.org, https://github.com/r-lib/cli", 160 | "BugReports": "https://github.com/r-lib/cli/issues", 161 | "Depends": [ 162 | "R (>= 3.4)" 163 | ], 164 | "Imports": [ 165 | "utils" 166 | ], 167 | "Suggests": [ 168 | "callr", 169 | "covr", 170 | "crayon", 171 | "digest", 172 | "glue (>= 1.6.0)", 173 | "grDevices", 174 | "htmltools", 175 | "htmlwidgets", 176 | "knitr", 177 | "methods", 178 | "processx", 179 | "ps (>= 1.3.4.9000)", 180 | "rlang (>= 1.0.2.9003)", 181 | "rmarkdown", 182 | "rprojroot", 183 | "rstudioapi", 184 | "testthat (>= 3.2.0)", 185 | "tibble", 186 | "whoami", 187 | "withr" 188 | ], 189 | "Config/Needs/website": "r-lib/asciicast, bench, brio, cpp11, decor, desc, fansi, prettyunits, sessioninfo, tidyverse/tidytemplate, usethis, vctrs", 190 | "Config/testthat/edition": "3", 191 | "Encoding": "UTF-8", 192 | "RoxygenNote": "7.3.2", 193 | "NeedsCompilation": "yes", 194 | "Author": "Gábor Csárdi [aut, cre], Hadley Wickham [ctb], Kirill Müller [ctb], Salim Brüggemann [ctb] (), Posit Software, PBC [cph, fnd]", 195 | "Maintainer": "Gábor Csárdi ", 196 | "Repository": "CRAN" 197 | }, 198 | "digest": { 199 | "Package": "digest", 200 | "Version": "0.6.37", 201 | "Source": "Repository", 202 | "Authors@R": "c(person(\"Dirk\", \"Eddelbuettel\", role = c(\"aut\", \"cre\"), email = \"edd@debian.org\", comment = c(ORCID = \"0000-0001-6419-907X\")), person(\"Antoine\", \"Lucas\", role=\"ctb\"), person(\"Jarek\", \"Tuszynski\", role=\"ctb\"), person(\"Henrik\", \"Bengtsson\", role=\"ctb\", comment = c(ORCID = \"0000-0002-7579-5165\")), person(\"Simon\", \"Urbanek\", role=\"ctb\", comment = c(ORCID = \"0000-0003-2297-1732\")), person(\"Mario\", \"Frasca\", role=\"ctb\"), person(\"Bryan\", \"Lewis\", role=\"ctb\"), person(\"Murray\", \"Stokely\", role=\"ctb\"), person(\"Hannes\", \"Muehleisen\", role=\"ctb\"), person(\"Duncan\", \"Murdoch\", role=\"ctb\"), person(\"Jim\", \"Hester\", role=\"ctb\"), person(\"Wush\", \"Wu\", role=\"ctb\", comment = c(ORCID = \"0000-0001-5180-0567\")), person(\"Qiang\", \"Kou\", role=\"ctb\", comment = c(ORCID = \"0000-0001-6786-5453\")), person(\"Thierry\", \"Onkelinx\", role=\"ctb\", comment = c(ORCID = \"0000-0001-8804-4216\")), person(\"Michel\", \"Lang\", role=\"ctb\", comment = c(ORCID = \"0000-0001-9754-0393\")), person(\"Viliam\", \"Simko\", role=\"ctb\"), person(\"Kurt\", \"Hornik\", role=\"ctb\", comment = c(ORCID = \"0000-0003-4198-9911\")), person(\"Radford\", \"Neal\", role=\"ctb\", comment = c(ORCID = \"0000-0002-2473-3407\")), person(\"Kendon\", \"Bell\", role=\"ctb\", comment = c(ORCID = \"0000-0002-9093-8312\")), person(\"Matthew\", \"de Queljoe\", role=\"ctb\"), person(\"Dmitry\", \"Selivanov\", role=\"ctb\"), person(\"Ion\", \"Suruceanu\", role=\"ctb\"), person(\"Bill\", \"Denney\", role=\"ctb\"), person(\"Dirk\", \"Schumacher\", role=\"ctb\"), person(\"András\", \"Svraka\", role=\"ctb\"), person(\"Sergey\", \"Fedorov\", role=\"ctb\"), person(\"Will\", \"Landau\", role=\"ctb\", comment = c(ORCID = \"0000-0003-1878-3253\")), person(\"Floris\", \"Vanderhaeghe\", role=\"ctb\", comment = c(ORCID = \"0000-0002-6378-6229\")), person(\"Kevin\", \"Tappe\", role=\"ctb\"), person(\"Harris\", \"McGehee\", role=\"ctb\"), person(\"Tim\", \"Mastny\", role=\"ctb\"), person(\"Aaron\", \"Peikert\", role=\"ctb\", comment = c(ORCID = \"0000-0001-7813-818X\")), person(\"Mark\", \"van der Loo\", role=\"ctb\", comment = c(ORCID = \"0000-0002-9807-4686\")), person(\"Chris\", \"Muir\", role=\"ctb\", comment = c(ORCID = \"0000-0003-2555-3878\")), person(\"Moritz\", \"Beller\", role=\"ctb\", comment = c(ORCID = \"0000-0003-4852-0526\")), person(\"Sebastian\", \"Campbell\", role=\"ctb\"), person(\"Winston\", \"Chang\", role=\"ctb\", comment = c(ORCID = \"0000-0002-1576-2126\")), person(\"Dean\", \"Attali\", role=\"ctb\", comment = c(ORCID = \"0000-0002-5645-3493\")), person(\"Michael\", \"Chirico\", role=\"ctb\", comment = c(ORCID = \"0000-0003-0787-087X\")), person(\"Kevin\", \"Ushey\", role=\"ctb\"))", 203 | "Date": "2024-08-19", 204 | "Title": "Create Compact Hash Digests of R Objects", 205 | "Description": "Implementation of a function 'digest()' for the creation of hash digests of arbitrary R objects (using the 'md5', 'sha-1', 'sha-256', 'crc32', 'xxhash', 'murmurhash', 'spookyhash', 'blake3', 'crc32c', 'xxh3_64', and 'xxh3_128' algorithms) permitting easy comparison of R language objects, as well as functions such as'hmac()' to create hash-based message authentication code. Please note that this package is not meant to be deployed for cryptographic purposes for which more comprehensive (and widely tested) libraries such as 'OpenSSL' should be used.", 206 | "URL": "https://github.com/eddelbuettel/digest, https://dirk.eddelbuettel.com/code/digest.html", 207 | "BugReports": "https://github.com/eddelbuettel/digest/issues", 208 | "Depends": [ 209 | "R (>= 3.3.0)" 210 | ], 211 | "Imports": [ 212 | "utils" 213 | ], 214 | "License": "GPL (>= 2)", 215 | "Suggests": [ 216 | "tinytest", 217 | "simplermarkdown" 218 | ], 219 | "VignetteBuilder": "simplermarkdown", 220 | "Encoding": "UTF-8", 221 | "NeedsCompilation": "yes", 222 | "Author": "Dirk Eddelbuettel [aut, cre] (), Antoine Lucas [ctb], Jarek Tuszynski [ctb], Henrik Bengtsson [ctb] (), Simon Urbanek [ctb] (), Mario Frasca [ctb], Bryan Lewis [ctb], Murray Stokely [ctb], Hannes Muehleisen [ctb], Duncan Murdoch [ctb], Jim Hester [ctb], Wush Wu [ctb] (), Qiang Kou [ctb] (), Thierry Onkelinx [ctb] (), Michel Lang [ctb] (), Viliam Simko [ctb], Kurt Hornik [ctb] (), Radford Neal [ctb] (), Kendon Bell [ctb] (), Matthew de Queljoe [ctb], Dmitry Selivanov [ctb], Ion Suruceanu [ctb], Bill Denney [ctb], Dirk Schumacher [ctb], András Svraka [ctb], Sergey Fedorov [ctb], Will Landau [ctb] (), Floris Vanderhaeghe [ctb] (), Kevin Tappe [ctb], Harris McGehee [ctb], Tim Mastny [ctb], Aaron Peikert [ctb] (), Mark van der Loo [ctb] (), Chris Muir [ctb] (), Moritz Beller [ctb] (), Sebastian Campbell [ctb], Winston Chang [ctb] (), Dean Attali [ctb] (), Michael Chirico [ctb] (), Kevin Ushey [ctb]", 223 | "Maintainer": "Dirk Eddelbuettel ", 224 | "Repository": "RSPM" 225 | }, 226 | "evaluate": { 227 | "Package": "evaluate", 228 | "Version": "1.0.3", 229 | "Source": "Repository", 230 | "Type": "Package", 231 | "Title": "Parsing and Evaluation Tools that Provide More Details than the Default", 232 | "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\")), person(\"Yihui\", \"Xie\", role = \"aut\", comment = c(ORCID = \"0000-0003-0645-5666\")), person(\"Michael\", \"Lawrence\", role = \"ctb\"), person(\"Thomas\", \"Kluyver\", role = \"ctb\"), person(\"Jeroen\", \"Ooms\", role = \"ctb\"), person(\"Barret\", \"Schloerke\", role = \"ctb\"), person(\"Adam\", \"Ryczkowski\", role = \"ctb\"), person(\"Hiroaki\", \"Yutani\", role = \"ctb\"), person(\"Michel\", \"Lang\", role = \"ctb\"), person(\"Karolis\", \"Koncevičius\", role = \"ctb\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", 233 | "Description": "Parsing and evaluation tools that make it easy to recreate the command line behaviour of R.", 234 | "License": "MIT + file LICENSE", 235 | "URL": "https://evaluate.r-lib.org/, https://github.com/r-lib/evaluate", 236 | "BugReports": "https://github.com/r-lib/evaluate/issues", 237 | "Depends": [ 238 | "R (>= 3.6.0)" 239 | ], 240 | "Suggests": [ 241 | "callr", 242 | "covr", 243 | "ggplot2 (>= 3.3.6)", 244 | "lattice", 245 | "methods", 246 | "pkgload", 247 | "rlang", 248 | "knitr", 249 | "testthat (>= 3.0.0)", 250 | "withr" 251 | ], 252 | "Config/Needs/website": "tidyverse/tidytemplate", 253 | "Config/testthat/edition": "3", 254 | "Encoding": "UTF-8", 255 | "RoxygenNote": "7.3.2", 256 | "NeedsCompilation": "no", 257 | "Author": "Hadley Wickham [aut, cre], Yihui Xie [aut] (), Michael Lawrence [ctb], Thomas Kluyver [ctb], Jeroen Ooms [ctb], Barret Schloerke [ctb], Adam Ryczkowski [ctb], Hiroaki Yutani [ctb], Michel Lang [ctb], Karolis Koncevičius [ctb], Posit Software, PBC [cph, fnd]", 258 | "Maintainer": "Hadley Wickham ", 259 | "Repository": "CRAN" 260 | }, 261 | "fastmap": { 262 | "Package": "fastmap", 263 | "Version": "1.2.0", 264 | "Source": "Repository", 265 | "Title": "Fast Data Structures", 266 | "Authors@R": "c( person(\"Winston\", \"Chang\", email = \"winston@posit.co\", role = c(\"aut\", \"cre\")), person(given = \"Posit Software, PBC\", role = c(\"cph\", \"fnd\")), person(given = \"Tessil\", role = \"cph\", comment = \"hopscotch_map library\") )", 267 | "Description": "Fast implementation of data structures, including a key-value store, stack, and queue. Environments are commonly used as key-value stores in R, but every time a new key is used, it is added to R's global symbol table, causing a small amount of memory leakage. This can be problematic in cases where many different keys are used. Fastmap avoids this memory leak issue by implementing the map using data structures in C++.", 268 | "License": "MIT + file LICENSE", 269 | "Encoding": "UTF-8", 270 | "RoxygenNote": "7.2.3", 271 | "Suggests": [ 272 | "testthat (>= 2.1.1)" 273 | ], 274 | "URL": "https://r-lib.github.io/fastmap/, https://github.com/r-lib/fastmap", 275 | "BugReports": "https://github.com/r-lib/fastmap/issues", 276 | "NeedsCompilation": "yes", 277 | "Author": "Winston Chang [aut, cre], Posit Software, PBC [cph, fnd], Tessil [cph] (hopscotch_map library)", 278 | "Maintainer": "Winston Chang ", 279 | "Repository": "RSPM" 280 | }, 281 | "fontawesome": { 282 | "Package": "fontawesome", 283 | "Version": "0.5.3", 284 | "Source": "Repository", 285 | "Type": "Package", 286 | "Title": "Easily Work with 'Font Awesome' Icons", 287 | "Description": "Easily and flexibly insert 'Font Awesome' icons into 'R Markdown' documents and 'Shiny' apps. These icons can be inserted into HTML content through inline 'SVG' tags or 'i' tags. There is also a utility function for exporting 'Font Awesome' icons as 'PNG' images for those situations where raster graphics are needed.", 288 | "Authors@R": "c( person(\"Richard\", \"Iannone\", , \"rich@posit.co\", c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0003-3925-190X\")), person(\"Christophe\", \"Dervieux\", , \"cderv@posit.co\", role = \"ctb\", comment = c(ORCID = \"0000-0003-4474-2498\")), person(\"Winston\", \"Chang\", , \"winston@posit.co\", role = \"ctb\"), person(\"Dave\", \"Gandy\", role = c(\"ctb\", \"cph\"), comment = \"Font-Awesome font\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", 289 | "License": "MIT + file LICENSE", 290 | "URL": "https://github.com/rstudio/fontawesome, https://rstudio.github.io/fontawesome/", 291 | "BugReports": "https://github.com/rstudio/fontawesome/issues", 292 | "Encoding": "UTF-8", 293 | "ByteCompile": "true", 294 | "RoxygenNote": "7.3.2", 295 | "Depends": [ 296 | "R (>= 3.3.0)" 297 | ], 298 | "Imports": [ 299 | "rlang (>= 1.0.6)", 300 | "htmltools (>= 0.5.1.1)" 301 | ], 302 | "Suggests": [ 303 | "covr", 304 | "dplyr (>= 1.0.8)", 305 | "gt (>= 0.9.0)", 306 | "knitr (>= 1.31)", 307 | "testthat (>= 3.0.0)", 308 | "rsvg" 309 | ], 310 | "Config/testthat/edition": "3", 311 | "NeedsCompilation": "no", 312 | "Author": "Richard Iannone [aut, cre] (), Christophe Dervieux [ctb] (), Winston Chang [ctb], Dave Gandy [ctb, cph] (Font-Awesome font), Posit Software, PBC [cph, fnd]", 313 | "Maintainer": "Richard Iannone ", 314 | "Repository": "RSPM" 315 | }, 316 | "fs": { 317 | "Package": "fs", 318 | "Version": "1.6.6", 319 | "Source": "Repository", 320 | "Title": "Cross-Platform File System Operations Based on 'libuv'", 321 | "Authors@R": "c( person(\"Jim\", \"Hester\", role = \"aut\"), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\"), person(\"Gábor\", \"Csárdi\", , \"csardi.gabor@gmail.com\", role = c(\"aut\", \"cre\")), person(\"libuv project contributors\", role = \"cph\", comment = \"libuv library\"), person(\"Joyent, Inc. and other Node contributors\", role = \"cph\", comment = \"libuv library\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", 322 | "Description": "A cross-platform interface to file system operations, built on top of the 'libuv' C library.", 323 | "License": "MIT + file LICENSE", 324 | "URL": "https://fs.r-lib.org, https://github.com/r-lib/fs", 325 | "BugReports": "https://github.com/r-lib/fs/issues", 326 | "Depends": [ 327 | "R (>= 3.6)" 328 | ], 329 | "Imports": [ 330 | "methods" 331 | ], 332 | "Suggests": [ 333 | "covr", 334 | "crayon", 335 | "knitr", 336 | "pillar (>= 1.0.0)", 337 | "rmarkdown", 338 | "spelling", 339 | "testthat (>= 3.0.0)", 340 | "tibble (>= 1.1.0)", 341 | "vctrs (>= 0.3.0)", 342 | "withr" 343 | ], 344 | "VignetteBuilder": "knitr", 345 | "ByteCompile": "true", 346 | "Config/Needs/website": "tidyverse/tidytemplate", 347 | "Config/testthat/edition": "3", 348 | "Copyright": "file COPYRIGHTS", 349 | "Encoding": "UTF-8", 350 | "Language": "en-US", 351 | "RoxygenNote": "7.2.3", 352 | "SystemRequirements": "GNU make", 353 | "NeedsCompilation": "yes", 354 | "Author": "Jim Hester [aut], Hadley Wickham [aut], Gábor Csárdi [aut, cre], libuv project contributors [cph] (libuv library), Joyent, Inc. and other Node contributors [cph] (libuv library), Posit Software, PBC [cph, fnd]", 355 | "Maintainer": "Gábor Csárdi ", 356 | "Repository": "CRAN" 357 | }, 358 | "glue": { 359 | "Package": "glue", 360 | "Version": "1.8.0", 361 | "Source": "Repository", 362 | "Title": "Interpreted String Literals", 363 | "Authors@R": "c( person(\"Jim\", \"Hester\", role = \"aut\", comment = c(ORCID = \"0000-0002-2739-7082\")), person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", 364 | "Description": "An implementation of interpreted string literals, inspired by Python's Literal String Interpolation and Docstrings and Julia's Triple-Quoted String Literals .", 365 | "License": "MIT + file LICENSE", 366 | "URL": "https://glue.tidyverse.org/, https://github.com/tidyverse/glue", 367 | "BugReports": "https://github.com/tidyverse/glue/issues", 368 | "Depends": [ 369 | "R (>= 3.6)" 370 | ], 371 | "Imports": [ 372 | "methods" 373 | ], 374 | "Suggests": [ 375 | "crayon", 376 | "DBI (>= 1.2.0)", 377 | "dplyr", 378 | "knitr", 379 | "magrittr", 380 | "rlang", 381 | "rmarkdown", 382 | "RSQLite", 383 | "testthat (>= 3.2.0)", 384 | "vctrs (>= 0.3.0)", 385 | "waldo (>= 0.5.3)", 386 | "withr" 387 | ], 388 | "VignetteBuilder": "knitr", 389 | "ByteCompile": "true", 390 | "Config/Needs/website": "bench, forcats, ggbeeswarm, ggplot2, R.utils, rprintf, tidyr, tidyverse/tidytemplate", 391 | "Config/testthat/edition": "3", 392 | "Encoding": "UTF-8", 393 | "RoxygenNote": "7.3.2", 394 | "NeedsCompilation": "yes", 395 | "Author": "Jim Hester [aut] (), Jennifer Bryan [aut, cre] (), Posit Software, PBC [cph, fnd]", 396 | "Maintainer": "Jennifer Bryan ", 397 | "Repository": "RSPM" 398 | }, 399 | "highr": { 400 | "Package": "highr", 401 | "Version": "0.11", 402 | "Source": "Repository", 403 | "Type": "Package", 404 | "Title": "Syntax Highlighting for R Source Code", 405 | "Authors@R": "c( person(\"Yihui\", \"Xie\", role = c(\"aut\", \"cre\"), email = \"xie@yihui.name\", comment = c(ORCID = \"0000-0003-0645-5666\")), person(\"Yixuan\", \"Qiu\", role = \"aut\"), person(\"Christopher\", \"Gandrud\", role = \"ctb\"), person(\"Qiang\", \"Li\", role = \"ctb\") )", 406 | "Description": "Provides syntax highlighting for R source code. Currently it supports LaTeX and HTML output. Source code of other languages is supported via Andre Simon's highlight package ().", 407 | "Depends": [ 408 | "R (>= 3.3.0)" 409 | ], 410 | "Imports": [ 411 | "xfun (>= 0.18)" 412 | ], 413 | "Suggests": [ 414 | "knitr", 415 | "markdown", 416 | "testit" 417 | ], 418 | "License": "GPL", 419 | "URL": "https://github.com/yihui/highr", 420 | "BugReports": "https://github.com/yihui/highr/issues", 421 | "VignetteBuilder": "knitr", 422 | "Encoding": "UTF-8", 423 | "RoxygenNote": "7.3.1", 424 | "NeedsCompilation": "no", 425 | "Author": "Yihui Xie [aut, cre] (), Yixuan Qiu [aut], Christopher Gandrud [ctb], Qiang Li [ctb]", 426 | "Maintainer": "Yihui Xie ", 427 | "Repository": "RSPM" 428 | }, 429 | "htmltools": { 430 | "Package": "htmltools", 431 | "Version": "0.5.8.1", 432 | "Source": "Repository", 433 | "Type": "Package", 434 | "Title": "Tools for HTML", 435 | "Authors@R": "c( person(\"Joe\", \"Cheng\", , \"joe@posit.co\", role = \"aut\"), person(\"Carson\", \"Sievert\", , \"carson@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-4958-2844\")), person(\"Barret\", \"Schloerke\", , \"barret@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0001-9986-114X\")), person(\"Winston\", \"Chang\", , \"winston@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0002-1576-2126\")), person(\"Yihui\", \"Xie\", , \"yihui@posit.co\", role = \"aut\"), person(\"Jeff\", \"Allen\", role = \"aut\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", 436 | "Description": "Tools for HTML generation and output.", 437 | "License": "GPL (>= 2)", 438 | "URL": "https://github.com/rstudio/htmltools, https://rstudio.github.io/htmltools/", 439 | "BugReports": "https://github.com/rstudio/htmltools/issues", 440 | "Depends": [ 441 | "R (>= 2.14.1)" 442 | ], 443 | "Imports": [ 444 | "base64enc", 445 | "digest", 446 | "fastmap (>= 1.1.0)", 447 | "grDevices", 448 | "rlang (>= 1.0.0)", 449 | "utils" 450 | ], 451 | "Suggests": [ 452 | "Cairo", 453 | "markdown", 454 | "ragg", 455 | "shiny", 456 | "testthat", 457 | "withr" 458 | ], 459 | "Enhances": [ 460 | "knitr" 461 | ], 462 | "Config/Needs/check": "knitr", 463 | "Config/Needs/website": "rstudio/quillt, bench", 464 | "Encoding": "UTF-8", 465 | "RoxygenNote": "7.3.1", 466 | "Collate": "'colors.R' 'fill.R' 'html_dependency.R' 'html_escape.R' 'html_print.R' 'htmltools-package.R' 'images.R' 'known_tags.R' 'selector.R' 'staticimports.R' 'tag_query.R' 'utils.R' 'tags.R' 'template.R'", 467 | "NeedsCompilation": "yes", 468 | "Author": "Joe Cheng [aut], Carson Sievert [aut, cre] (), Barret Schloerke [aut] (), Winston Chang [aut] (), Yihui Xie [aut], Jeff Allen [aut], Posit Software, PBC [cph, fnd]", 469 | "Maintainer": "Carson Sievert ", 470 | "Repository": "RSPM" 471 | }, 472 | "jquerylib": { 473 | "Package": "jquerylib", 474 | "Version": "0.1.4", 475 | "Source": "Repository", 476 | "Title": "Obtain 'jQuery' as an HTML Dependency Object", 477 | "Authors@R": "c( person(\"Carson\", \"Sievert\", role = c(\"aut\", \"cre\"), email = \"carson@rstudio.com\", comment = c(ORCID = \"0000-0002-4958-2844\")), person(\"Joe\", \"Cheng\", role = \"aut\", email = \"joe@rstudio.com\"), person(family = \"RStudio\", role = \"cph\"), person(family = \"jQuery Foundation\", role = \"cph\", comment = \"jQuery library and jQuery UI library\"), person(family = \"jQuery contributors\", role = c(\"ctb\", \"cph\"), comment = \"jQuery library; authors listed in inst/lib/jquery-AUTHORS.txt\") )", 478 | "Description": "Obtain any major version of 'jQuery' () and use it in any webpage generated by 'htmltools' (e.g. 'shiny', 'htmlwidgets', and 'rmarkdown'). Most R users don't need to use this package directly, but other R packages (e.g. 'shiny', 'rmarkdown', etc.) depend on this package to avoid bundling redundant copies of 'jQuery'.", 479 | "License": "MIT + file LICENSE", 480 | "Encoding": "UTF-8", 481 | "Config/testthat/edition": "3", 482 | "RoxygenNote": "7.0.2", 483 | "Imports": [ 484 | "htmltools" 485 | ], 486 | "Suggests": [ 487 | "testthat" 488 | ], 489 | "NeedsCompilation": "no", 490 | "Author": "Carson Sievert [aut, cre] (), Joe Cheng [aut], RStudio [cph], jQuery Foundation [cph] (jQuery library and jQuery UI library), jQuery contributors [ctb, cph] (jQuery library; authors listed in inst/lib/jquery-AUTHORS.txt)", 491 | "Maintainer": "Carson Sievert ", 492 | "Repository": "RSPM" 493 | }, 494 | "jsonlite": { 495 | "Package": "jsonlite", 496 | "Version": "2.0.0", 497 | "Source": "Repository", 498 | "Title": "A Simple and Robust JSON Parser and Generator for R", 499 | "License": "MIT + file LICENSE", 500 | "Depends": [ 501 | "methods" 502 | ], 503 | "Authors@R": "c( person(\"Jeroen\", \"Ooms\", role = c(\"aut\", \"cre\"), email = \"jeroenooms@gmail.com\", comment = c(ORCID = \"0000-0002-4035-0289\")), person(\"Duncan\", \"Temple Lang\", role = \"ctb\"), person(\"Lloyd\", \"Hilaiel\", role = \"cph\", comment=\"author of bundled libyajl\"))", 504 | "URL": "https://jeroen.r-universe.dev/jsonlite https://arxiv.org/abs/1403.2805", 505 | "BugReports": "https://github.com/jeroen/jsonlite/issues", 506 | "Maintainer": "Jeroen Ooms ", 507 | "VignetteBuilder": "knitr, R.rsp", 508 | "Description": "A reasonably fast JSON parser and generator, optimized for statistical data and the web. Offers simple, flexible tools for working with JSON in R, and is particularly powerful for building pipelines and interacting with a web API. The implementation is based on the mapping described in the vignette (Ooms, 2014). In addition to converting JSON data from/to R objects, 'jsonlite' contains functions to stream, validate, and prettify JSON data. The unit tests included with the package verify that all edge cases are encoded and decoded consistently for use with dynamic data in systems and applications.", 509 | "Suggests": [ 510 | "httr", 511 | "vctrs", 512 | "testthat", 513 | "knitr", 514 | "rmarkdown", 515 | "R.rsp", 516 | "sf" 517 | ], 518 | "RoxygenNote": "7.3.2", 519 | "Encoding": "UTF-8", 520 | "NeedsCompilation": "yes", 521 | "Author": "Jeroen Ooms [aut, cre] (), Duncan Temple Lang [ctb], Lloyd Hilaiel [cph] (author of bundled libyajl)", 522 | "Repository": "CRAN" 523 | }, 524 | "knitr": { 525 | "Package": "knitr", 526 | "Version": "1.50", 527 | "Source": "Repository", 528 | "Type": "Package", 529 | "Title": "A General-Purpose Package for Dynamic Report Generation in R", 530 | "Authors@R": "c( person(\"Yihui\", \"Xie\", role = c(\"aut\", \"cre\"), email = \"xie@yihui.name\", comment = c(ORCID = \"0000-0003-0645-5666\", URL = \"https://yihui.org\")), person(\"Abhraneel\", \"Sarma\", role = \"ctb\"), person(\"Adam\", \"Vogt\", role = \"ctb\"), person(\"Alastair\", \"Andrew\", role = \"ctb\"), person(\"Alex\", \"Zvoleff\", role = \"ctb\"), person(\"Amar\", \"Al-Zubaidi\", role = \"ctb\"), person(\"Andre\", \"Simon\", role = \"ctb\", comment = \"the CSS files under inst/themes/ were derived from the Highlight package http://www.andre-simon.de\"), person(\"Aron\", \"Atkins\", role = \"ctb\"), person(\"Aaron\", \"Wolen\", role = \"ctb\"), person(\"Ashley\", \"Manton\", role = \"ctb\"), person(\"Atsushi\", \"Yasumoto\", role = \"ctb\", comment = c(ORCID = \"0000-0002-8335-495X\")), person(\"Ben\", \"Baumer\", role = \"ctb\"), person(\"Brian\", \"Diggs\", role = \"ctb\"), person(\"Brian\", \"Zhang\", role = \"ctb\"), person(\"Bulat\", \"Yapparov\", role = \"ctb\"), person(\"Cassio\", \"Pereira\", role = \"ctb\"), person(\"Christophe\", \"Dervieux\", role = \"ctb\"), person(\"David\", \"Hall\", role = \"ctb\"), person(\"David\", \"Hugh-Jones\", role = \"ctb\"), person(\"David\", \"Robinson\", role = \"ctb\"), person(\"Doug\", \"Hemken\", role = \"ctb\"), person(\"Duncan\", \"Murdoch\", role = \"ctb\"), person(\"Elio\", \"Campitelli\", role = \"ctb\"), person(\"Ellis\", \"Hughes\", role = \"ctb\"), person(\"Emily\", \"Riederer\", role = \"ctb\"), person(\"Fabian\", \"Hirschmann\", role = \"ctb\"), person(\"Fitch\", \"Simeon\", role = \"ctb\"), person(\"Forest\", \"Fang\", role = \"ctb\"), person(c(\"Frank\", \"E\", \"Harrell\", \"Jr\"), role = \"ctb\", comment = \"the Sweavel package at inst/misc/Sweavel.sty\"), person(\"Garrick\", \"Aden-Buie\", role = \"ctb\"), person(\"Gregoire\", \"Detrez\", role = \"ctb\"), person(\"Hadley\", \"Wickham\", role = \"ctb\"), person(\"Hao\", \"Zhu\", role = \"ctb\"), person(\"Heewon\", \"Jeon\", role = \"ctb\"), person(\"Henrik\", \"Bengtsson\", role = \"ctb\"), person(\"Hiroaki\", \"Yutani\", role = \"ctb\"), person(\"Ian\", \"Lyttle\", role = \"ctb\"), person(\"Hodges\", \"Daniel\", role = \"ctb\"), person(\"Jacob\", \"Bien\", role = \"ctb\"), person(\"Jake\", \"Burkhead\", role = \"ctb\"), person(\"James\", \"Manton\", role = \"ctb\"), person(\"Jared\", \"Lander\", role = \"ctb\"), person(\"Jason\", \"Punyon\", role = \"ctb\"), person(\"Javier\", \"Luraschi\", role = \"ctb\"), person(\"Jeff\", \"Arnold\", role = \"ctb\"), person(\"Jenny\", \"Bryan\", role = \"ctb\"), person(\"Jeremy\", \"Ashkenas\", role = c(\"ctb\", \"cph\"), comment = \"the CSS file at inst/misc/docco-classic.css\"), person(\"Jeremy\", \"Stephens\", role = \"ctb\"), person(\"Jim\", \"Hester\", role = \"ctb\"), person(\"Joe\", \"Cheng\", role = \"ctb\"), person(\"Johannes\", \"Ranke\", role = \"ctb\"), person(\"John\", \"Honaker\", role = \"ctb\"), person(\"John\", \"Muschelli\", role = \"ctb\"), person(\"Jonathan\", \"Keane\", role = \"ctb\"), person(\"JJ\", \"Allaire\", role = \"ctb\"), person(\"Johan\", \"Toloe\", role = \"ctb\"), person(\"Jonathan\", \"Sidi\", role = \"ctb\"), person(\"Joseph\", \"Larmarange\", role = \"ctb\"), person(\"Julien\", \"Barnier\", role = \"ctb\"), person(\"Kaiyin\", \"Zhong\", role = \"ctb\"), person(\"Kamil\", \"Slowikowski\", role = \"ctb\"), person(\"Karl\", \"Forner\", role = \"ctb\"), person(c(\"Kevin\", \"K.\"), \"Smith\", role = \"ctb\"), person(\"Kirill\", \"Mueller\", role = \"ctb\"), person(\"Kohske\", \"Takahashi\", role = \"ctb\"), person(\"Lorenz\", \"Walthert\", role = \"ctb\"), person(\"Lucas\", \"Gallindo\", role = \"ctb\"), person(\"Marius\", \"Hofert\", role = \"ctb\"), person(\"Martin\", \"Modrák\", role = \"ctb\"), person(\"Michael\", \"Chirico\", role = \"ctb\"), person(\"Michael\", \"Friendly\", role = \"ctb\"), person(\"Michal\", \"Bojanowski\", role = \"ctb\"), person(\"Michel\", \"Kuhlmann\", role = \"ctb\"), person(\"Miller\", \"Patrick\", role = \"ctb\"), person(\"Nacho\", \"Caballero\", role = \"ctb\"), person(\"Nick\", \"Salkowski\", role = \"ctb\"), person(\"Niels Richard\", \"Hansen\", role = \"ctb\"), person(\"Noam\", \"Ross\", role = \"ctb\"), person(\"Obada\", \"Mahdi\", role = \"ctb\"), person(\"Pavel N.\", \"Krivitsky\", role = \"ctb\", comment=c(ORCID = \"0000-0002-9101-3362\")), person(\"Pedro\", \"Faria\", role = \"ctb\"), person(\"Qiang\", \"Li\", role = \"ctb\"), person(\"Ramnath\", \"Vaidyanathan\", role = \"ctb\"), person(\"Richard\", \"Cotton\", role = \"ctb\"), person(\"Robert\", \"Krzyzanowski\", role = \"ctb\"), person(\"Rodrigo\", \"Copetti\", role = \"ctb\"), person(\"Romain\", \"Francois\", role = \"ctb\"), person(\"Ruaridh\", \"Williamson\", role = \"ctb\"), person(\"Sagiru\", \"Mati\", role = \"ctb\", comment = c(ORCID = \"0000-0003-1413-3974\")), person(\"Scott\", \"Kostyshak\", role = \"ctb\"), person(\"Sebastian\", \"Meyer\", role = \"ctb\"), person(\"Sietse\", \"Brouwer\", role = \"ctb\"), person(c(\"Simon\", \"de\"), \"Bernard\", role = \"ctb\"), person(\"Sylvain\", \"Rousseau\", role = \"ctb\"), person(\"Taiyun\", \"Wei\", role = \"ctb\"), person(\"Thibaut\", \"Assus\", role = \"ctb\"), person(\"Thibaut\", \"Lamadon\", role = \"ctb\"), person(\"Thomas\", \"Leeper\", role = \"ctb\"), person(\"Tim\", \"Mastny\", role = \"ctb\"), person(\"Tom\", \"Torsney-Weir\", role = \"ctb\"), person(\"Trevor\", \"Davis\", role = \"ctb\"), person(\"Viktoras\", \"Veitas\", role = \"ctb\"), person(\"Weicheng\", \"Zhu\", role = \"ctb\"), person(\"Wush\", \"Wu\", role = \"ctb\"), person(\"Zachary\", \"Foster\", role = \"ctb\"), person(\"Zhian N.\", \"Kamvar\", role = \"ctb\", comment = c(ORCID = \"0000-0003-1458-7108\")), person(given = \"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", 531 | "Description": "Provides a general-purpose tool for dynamic report generation in R using Literate Programming techniques.", 532 | "Depends": [ 533 | "R (>= 3.6.0)" 534 | ], 535 | "Imports": [ 536 | "evaluate (>= 0.15)", 537 | "highr (>= 0.11)", 538 | "methods", 539 | "tools", 540 | "xfun (>= 0.51)", 541 | "yaml (>= 2.1.19)" 542 | ], 543 | "Suggests": [ 544 | "bslib", 545 | "codetools", 546 | "DBI (>= 0.4-1)", 547 | "digest", 548 | "formatR", 549 | "gifski", 550 | "gridSVG", 551 | "htmlwidgets (>= 0.7)", 552 | "jpeg", 553 | "JuliaCall (>= 0.11.1)", 554 | "magick", 555 | "litedown", 556 | "markdown (>= 1.3)", 557 | "png", 558 | "ragg", 559 | "reticulate (>= 1.4)", 560 | "rgl (>= 0.95.1201)", 561 | "rlang", 562 | "rmarkdown", 563 | "sass", 564 | "showtext", 565 | "styler (>= 1.2.0)", 566 | "targets (>= 0.6.0)", 567 | "testit", 568 | "tibble", 569 | "tikzDevice (>= 0.10)", 570 | "tinytex (>= 0.56)", 571 | "webshot", 572 | "rstudioapi", 573 | "svglite" 574 | ], 575 | "License": "GPL", 576 | "URL": "https://yihui.org/knitr/", 577 | "BugReports": "https://github.com/yihui/knitr/issues", 578 | "Encoding": "UTF-8", 579 | "VignetteBuilder": "litedown, knitr", 580 | "SystemRequirements": "Package vignettes based on R Markdown v2 or reStructuredText require Pandoc (http://pandoc.org). The function rst2pdf() requires rst2pdf (https://github.com/rst2pdf/rst2pdf).", 581 | "Collate": "'block.R' 'cache.R' 'citation.R' 'hooks-html.R' 'plot.R' 'utils.R' 'defaults.R' 'concordance.R' 'engine.R' 'highlight.R' 'themes.R' 'header.R' 'hooks-asciidoc.R' 'hooks-chunk.R' 'hooks-extra.R' 'hooks-latex.R' 'hooks-md.R' 'hooks-rst.R' 'hooks-textile.R' 'hooks.R' 'output.R' 'package.R' 'pandoc.R' 'params.R' 'parser.R' 'pattern.R' 'rocco.R' 'spin.R' 'table.R' 'template.R' 'utils-conversion.R' 'utils-rd2html.R' 'utils-string.R' 'utils-sweave.R' 'utils-upload.R' 'utils-vignettes.R' 'zzz.R'", 582 | "RoxygenNote": "7.3.2", 583 | "NeedsCompilation": "no", 584 | "Author": "Yihui Xie [aut, cre] (, https://yihui.org), Abhraneel Sarma [ctb], Adam Vogt [ctb], Alastair Andrew [ctb], Alex Zvoleff [ctb], Amar Al-Zubaidi [ctb], Andre Simon [ctb] (the CSS files under inst/themes/ were derived from the Highlight package http://www.andre-simon.de), Aron Atkins [ctb], Aaron Wolen [ctb], Ashley Manton [ctb], Atsushi Yasumoto [ctb] (), Ben Baumer [ctb], Brian Diggs [ctb], Brian Zhang [ctb], Bulat Yapparov [ctb], Cassio Pereira [ctb], Christophe Dervieux [ctb], David Hall [ctb], David Hugh-Jones [ctb], David Robinson [ctb], Doug Hemken [ctb], Duncan Murdoch [ctb], Elio Campitelli [ctb], Ellis Hughes [ctb], Emily Riederer [ctb], Fabian Hirschmann [ctb], Fitch Simeon [ctb], Forest Fang [ctb], Frank E Harrell Jr [ctb] (the Sweavel package at inst/misc/Sweavel.sty), Garrick Aden-Buie [ctb], Gregoire Detrez [ctb], Hadley Wickham [ctb], Hao Zhu [ctb], Heewon Jeon [ctb], Henrik Bengtsson [ctb], Hiroaki Yutani [ctb], Ian Lyttle [ctb], Hodges Daniel [ctb], Jacob Bien [ctb], Jake Burkhead [ctb], James Manton [ctb], Jared Lander [ctb], Jason Punyon [ctb], Javier Luraschi [ctb], Jeff Arnold [ctb], Jenny Bryan [ctb], Jeremy Ashkenas [ctb, cph] (the CSS file at inst/misc/docco-classic.css), Jeremy Stephens [ctb], Jim Hester [ctb], Joe Cheng [ctb], Johannes Ranke [ctb], John Honaker [ctb], John Muschelli [ctb], Jonathan Keane [ctb], JJ Allaire [ctb], Johan Toloe [ctb], Jonathan Sidi [ctb], Joseph Larmarange [ctb], Julien Barnier [ctb], Kaiyin Zhong [ctb], Kamil Slowikowski [ctb], Karl Forner [ctb], Kevin K. Smith [ctb], Kirill Mueller [ctb], Kohske Takahashi [ctb], Lorenz Walthert [ctb], Lucas Gallindo [ctb], Marius Hofert [ctb], Martin Modrák [ctb], Michael Chirico [ctb], Michael Friendly [ctb], Michal Bojanowski [ctb], Michel Kuhlmann [ctb], Miller Patrick [ctb], Nacho Caballero [ctb], Nick Salkowski [ctb], Niels Richard Hansen [ctb], Noam Ross [ctb], Obada Mahdi [ctb], Pavel N. Krivitsky [ctb] (), Pedro Faria [ctb], Qiang Li [ctb], Ramnath Vaidyanathan [ctb], Richard Cotton [ctb], Robert Krzyzanowski [ctb], Rodrigo Copetti [ctb], Romain Francois [ctb], Ruaridh Williamson [ctb], Sagiru Mati [ctb] (), Scott Kostyshak [ctb], Sebastian Meyer [ctb], Sietse Brouwer [ctb], Simon de Bernard [ctb], Sylvain Rousseau [ctb], Taiyun Wei [ctb], Thibaut Assus [ctb], Thibaut Lamadon [ctb], Thomas Leeper [ctb], Tim Mastny [ctb], Tom Torsney-Weir [ctb], Trevor Davis [ctb], Viktoras Veitas [ctb], Weicheng Zhu [ctb], Wush Wu [ctb], Zachary Foster [ctb], Zhian N. Kamvar [ctb] (), Posit Software, PBC [cph, fnd]", 585 | "Maintainer": "Yihui Xie ", 586 | "Repository": "CRAN" 587 | }, 588 | "lifecycle": { 589 | "Package": "lifecycle", 590 | "Version": "1.0.4", 591 | "Source": "Repository", 592 | "Title": "Manage the Life Cycle of your Package Functions", 593 | "Authors@R": "c( person(\"Lionel\", \"Henry\", , \"lionel@posit.co\", role = c(\"aut\", \"cre\")), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", 594 | "Description": "Manage the life cycle of your exported functions with shared conventions, documentation badges, and user-friendly deprecation warnings.", 595 | "License": "MIT + file LICENSE", 596 | "URL": "https://lifecycle.r-lib.org/, https://github.com/r-lib/lifecycle", 597 | "BugReports": "https://github.com/r-lib/lifecycle/issues", 598 | "Depends": [ 599 | "R (>= 3.6)" 600 | ], 601 | "Imports": [ 602 | "cli (>= 3.4.0)", 603 | "glue", 604 | "rlang (>= 1.1.0)" 605 | ], 606 | "Suggests": [ 607 | "covr", 608 | "crayon", 609 | "knitr", 610 | "lintr", 611 | "rmarkdown", 612 | "testthat (>= 3.0.1)", 613 | "tibble", 614 | "tidyverse", 615 | "tools", 616 | "vctrs", 617 | "withr" 618 | ], 619 | "VignetteBuilder": "knitr", 620 | "Config/Needs/website": "tidyverse/tidytemplate, usethis", 621 | "Config/testthat/edition": "3", 622 | "Encoding": "UTF-8", 623 | "RoxygenNote": "7.2.1", 624 | "NeedsCompilation": "no", 625 | "Author": "Lionel Henry [aut, cre], Hadley Wickham [aut] (), Posit Software, PBC [cph, fnd]", 626 | "Maintainer": "Lionel Henry ", 627 | "Repository": "RSPM" 628 | }, 629 | "memoise": { 630 | "Package": "memoise", 631 | "Version": "2.0.1", 632 | "Source": "Repository", 633 | "Title": "'Memoisation' of Functions", 634 | "Authors@R": "c(person(given = \"Hadley\", family = \"Wickham\", role = \"aut\", email = \"hadley@rstudio.com\"), person(given = \"Jim\", family = \"Hester\", role = \"aut\"), person(given = \"Winston\", family = \"Chang\", role = c(\"aut\", \"cre\"), email = \"winston@rstudio.com\"), person(given = \"Kirill\", family = \"Müller\", role = \"aut\", email = \"krlmlr+r@mailbox.org\"), person(given = \"Daniel\", family = \"Cook\", role = \"aut\", email = \"danielecook@gmail.com\"), person(given = \"Mark\", family = \"Edmondson\", role = \"ctb\", email = \"r@sunholo.com\"))", 635 | "Description": "Cache the results of a function so that when you call it again with the same arguments it returns the previously computed value.", 636 | "License": "MIT + file LICENSE", 637 | "URL": "https://memoise.r-lib.org, https://github.com/r-lib/memoise", 638 | "BugReports": "https://github.com/r-lib/memoise/issues", 639 | "Imports": [ 640 | "rlang (>= 0.4.10)", 641 | "cachem" 642 | ], 643 | "Suggests": [ 644 | "digest", 645 | "aws.s3", 646 | "covr", 647 | "googleAuthR", 648 | "googleCloudStorageR", 649 | "httr", 650 | "testthat" 651 | ], 652 | "Encoding": "UTF-8", 653 | "RoxygenNote": "7.1.2", 654 | "NeedsCompilation": "no", 655 | "Author": "Hadley Wickham [aut], Jim Hester [aut], Winston Chang [aut, cre], Kirill Müller [aut], Daniel Cook [aut], Mark Edmondson [ctb]", 656 | "Maintainer": "Winston Chang ", 657 | "Repository": "RSPM" 658 | }, 659 | "mime": { 660 | "Package": "mime", 661 | "Version": "0.13", 662 | "Source": "Repository", 663 | "Type": "Package", 664 | "Title": "Map Filenames to MIME Types", 665 | "Authors@R": "c( person(\"Yihui\", \"Xie\", role = c(\"aut\", \"cre\"), email = \"xie@yihui.name\", comment = c(ORCID = \"0000-0003-0645-5666\", URL = \"https://yihui.org\")), person(\"Jeffrey\", \"Horner\", role = \"ctb\"), person(\"Beilei\", \"Bian\", role = \"ctb\") )", 666 | "Description": "Guesses the MIME type from a filename extension using the data derived from /etc/mime.types in UNIX-type systems.", 667 | "Imports": [ 668 | "tools" 669 | ], 670 | "License": "GPL", 671 | "URL": "https://github.com/yihui/mime", 672 | "BugReports": "https://github.com/yihui/mime/issues", 673 | "RoxygenNote": "7.3.2", 674 | "Encoding": "UTF-8", 675 | "NeedsCompilation": "yes", 676 | "Author": "Yihui Xie [aut, cre] (, https://yihui.org), Jeffrey Horner [ctb], Beilei Bian [ctb]", 677 | "Maintainer": "Yihui Xie ", 678 | "Repository": "CRAN" 679 | }, 680 | "rappdirs": { 681 | "Package": "rappdirs", 682 | "Version": "0.3.3", 683 | "Source": "Repository", 684 | "Type": "Package", 685 | "Title": "Application Directories: Determine Where to Save Data, Caches, and Logs", 686 | "Authors@R": "c(person(given = \"Hadley\", family = \"Wickham\", role = c(\"trl\", \"cre\", \"cph\"), email = \"hadley@rstudio.com\"), person(given = \"RStudio\", role = \"cph\"), person(given = \"Sridhar\", family = \"Ratnakumar\", role = \"aut\"), person(given = \"Trent\", family = \"Mick\", role = \"aut\"), person(given = \"ActiveState\", role = \"cph\", comment = \"R/appdir.r, R/cache.r, R/data.r, R/log.r translated from appdirs\"), person(given = \"Eddy\", family = \"Petrisor\", role = \"ctb\"), person(given = \"Trevor\", family = \"Davis\", role = c(\"trl\", \"aut\")), person(given = \"Gabor\", family = \"Csardi\", role = \"ctb\"), person(given = \"Gregory\", family = \"Jefferis\", role = \"ctb\"))", 687 | "Description": "An easy way to determine which directories on the users computer you should use to save data, caches and logs. A port of Python's 'Appdirs' () to R.", 688 | "License": "MIT + file LICENSE", 689 | "URL": "https://rappdirs.r-lib.org, https://github.com/r-lib/rappdirs", 690 | "BugReports": "https://github.com/r-lib/rappdirs/issues", 691 | "Depends": [ 692 | "R (>= 3.2)" 693 | ], 694 | "Suggests": [ 695 | "roxygen2", 696 | "testthat (>= 3.0.0)", 697 | "covr", 698 | "withr" 699 | ], 700 | "Copyright": "Original python appdirs module copyright (c) 2010 ActiveState Software Inc. R port copyright Hadley Wickham, RStudio. See file LICENSE for details.", 701 | "Encoding": "UTF-8", 702 | "RoxygenNote": "7.1.1", 703 | "Config/testthat/edition": "3", 704 | "NeedsCompilation": "yes", 705 | "Author": "Hadley Wickham [trl, cre, cph], RStudio [cph], Sridhar Ratnakumar [aut], Trent Mick [aut], ActiveState [cph] (R/appdir.r, R/cache.r, R/data.r, R/log.r translated from appdirs), Eddy Petrisor [ctb], Trevor Davis [trl, aut], Gabor Csardi [ctb], Gregory Jefferis [ctb]", 706 | "Maintainer": "Hadley Wickham ", 707 | "Repository": "RSPM" 708 | }, 709 | "renv": { 710 | "Package": "renv", 711 | "Version": "1.1.4", 712 | "Source": "Repository", 713 | "Type": "Package", 714 | "Title": "Project Environments", 715 | "Authors@R": "c( person(\"Kevin\", \"Ushey\", role = c(\"aut\", \"cre\"), email = \"kevin@rstudio.com\", comment = c(ORCID = \"0000-0003-2880-7407\")), person(\"Hadley\", \"Wickham\", role = c(\"aut\"), email = \"hadley@rstudio.com\", comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", 716 | "Description": "A dependency management toolkit for R. Using 'renv', you can create and manage project-local R libraries, save the state of these libraries to a 'lockfile', and later restore your library as required. Together, these tools can help make your projects more isolated, portable, and reproducible.", 717 | "License": "MIT + file LICENSE", 718 | "URL": "https://rstudio.github.io/renv/, https://github.com/rstudio/renv", 719 | "BugReports": "https://github.com/rstudio/renv/issues", 720 | "Imports": [ 721 | "utils" 722 | ], 723 | "Suggests": [ 724 | "BiocManager", 725 | "cli", 726 | "compiler", 727 | "covr", 728 | "cpp11", 729 | "devtools", 730 | "gitcreds", 731 | "jsonlite", 732 | "jsonvalidate", 733 | "knitr", 734 | "miniUI", 735 | "modules", 736 | "packrat", 737 | "pak", 738 | "R6", 739 | "remotes", 740 | "reticulate", 741 | "rmarkdown", 742 | "rstudioapi", 743 | "shiny", 744 | "testthat", 745 | "uuid", 746 | "waldo", 747 | "yaml", 748 | "webfakes" 749 | ], 750 | "Encoding": "UTF-8", 751 | "RoxygenNote": "7.3.2", 752 | "VignetteBuilder": "knitr", 753 | "Config/Needs/website": "tidyverse/tidytemplate", 754 | "Config/testthat/edition": "3", 755 | "Config/testthat/parallel": "true", 756 | "Config/testthat/start-first": "bioconductor,python,install,restore,snapshot,retrieve,remotes", 757 | "NeedsCompilation": "no", 758 | "Author": "Kevin Ushey [aut, cre] (), Hadley Wickham [aut] (), Posit Software, PBC [cph, fnd]", 759 | "Maintainer": "Kevin Ushey ", 760 | "Repository": "CRAN" 761 | }, 762 | "rlang": { 763 | "Package": "rlang", 764 | "Version": "1.1.6", 765 | "Source": "Repository", 766 | "Title": "Functions for Base Types and Core R and 'Tidyverse' Features", 767 | "Description": "A toolbox for working with base types, core R features like the condition system, and core 'Tidyverse' features like tidy evaluation.", 768 | "Authors@R": "c( person(\"Lionel\", \"Henry\", ,\"lionel@posit.co\", c(\"aut\", \"cre\")), person(\"Hadley\", \"Wickham\", ,\"hadley@posit.co\", \"aut\"), person(given = \"mikefc\", email = \"mikefc@coolbutuseless.com\", role = \"cph\", comment = \"Hash implementation based on Mike's xxhashlite\"), person(given = \"Yann\", family = \"Collet\", role = \"cph\", comment = \"Author of the embedded xxHash library\"), person(given = \"Posit, PBC\", role = c(\"cph\", \"fnd\")) )", 769 | "License": "MIT + file LICENSE", 770 | "ByteCompile": "true", 771 | "Biarch": "true", 772 | "Depends": [ 773 | "R (>= 3.5.0)" 774 | ], 775 | "Imports": [ 776 | "utils" 777 | ], 778 | "Suggests": [ 779 | "cli (>= 3.1.0)", 780 | "covr", 781 | "crayon", 782 | "desc", 783 | "fs", 784 | "glue", 785 | "knitr", 786 | "magrittr", 787 | "methods", 788 | "pillar", 789 | "pkgload", 790 | "rmarkdown", 791 | "stats", 792 | "testthat (>= 3.2.0)", 793 | "tibble", 794 | "usethis", 795 | "vctrs (>= 0.2.3)", 796 | "withr" 797 | ], 798 | "Enhances": [ 799 | "winch" 800 | ], 801 | "Encoding": "UTF-8", 802 | "RoxygenNote": "7.3.2", 803 | "URL": "https://rlang.r-lib.org, https://github.com/r-lib/rlang", 804 | "BugReports": "https://github.com/r-lib/rlang/issues", 805 | "Config/build/compilation-database": "true", 806 | "Config/testthat/edition": "3", 807 | "Config/Needs/website": "dplyr, tidyverse/tidytemplate", 808 | "NeedsCompilation": "yes", 809 | "Author": "Lionel Henry [aut, cre], Hadley Wickham [aut], mikefc [cph] (Hash implementation based on Mike's xxhashlite), Yann Collet [cph] (Author of the embedded xxHash library), Posit, PBC [cph, fnd]", 810 | "Maintainer": "Lionel Henry ", 811 | "Repository": "CRAN" 812 | }, 813 | "rmarkdown": { 814 | "Package": "rmarkdown", 815 | "Version": "2.29", 816 | "Source": "Repository", 817 | "Type": "Package", 818 | "Title": "Dynamic Documents for R", 819 | "Authors@R": "c( person(\"JJ\", \"Allaire\", , \"jj@posit.co\", role = \"aut\"), person(\"Yihui\", \"Xie\", , \"xie@yihui.name\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0003-0645-5666\")), person(\"Christophe\", \"Dervieux\", , \"cderv@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-4474-2498\")), person(\"Jonathan\", \"McPherson\", , \"jonathan@posit.co\", role = \"aut\"), person(\"Javier\", \"Luraschi\", role = \"aut\"), person(\"Kevin\", \"Ushey\", , \"kevin@posit.co\", role = \"aut\"), person(\"Aron\", \"Atkins\", , \"aron@posit.co\", role = \"aut\"), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\"), person(\"Joe\", \"Cheng\", , \"joe@posit.co\", role = \"aut\"), person(\"Winston\", \"Chang\", , \"winston@posit.co\", role = \"aut\"), person(\"Richard\", \"Iannone\", , \"rich@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-3925-190X\")), person(\"Andrew\", \"Dunning\", role = \"ctb\", comment = c(ORCID = \"0000-0003-0464-5036\")), person(\"Atsushi\", \"Yasumoto\", role = c(\"ctb\", \"cph\"), comment = c(ORCID = \"0000-0002-8335-495X\", cph = \"Number sections Lua filter\")), person(\"Barret\", \"Schloerke\", role = \"ctb\"), person(\"Carson\", \"Sievert\", role = \"ctb\", comment = c(ORCID = \"0000-0002-4958-2844\")), person(\"Devon\", \"Ryan\", , \"dpryan79@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0002-8549-0971\")), person(\"Frederik\", \"Aust\", , \"frederik.aust@uni-koeln.de\", role = \"ctb\", comment = c(ORCID = \"0000-0003-4900-788X\")), person(\"Jeff\", \"Allen\", , \"jeff@posit.co\", role = \"ctb\"), person(\"JooYoung\", \"Seo\", role = \"ctb\", comment = c(ORCID = \"0000-0002-4064-6012\")), person(\"Malcolm\", \"Barrett\", role = \"ctb\"), person(\"Rob\", \"Hyndman\", , \"Rob.Hyndman@monash.edu\", role = \"ctb\"), person(\"Romain\", \"Lesur\", role = \"ctb\"), person(\"Roy\", \"Storey\", role = \"ctb\"), person(\"Ruben\", \"Arslan\", , \"ruben.arslan@uni-goettingen.de\", role = \"ctb\"), person(\"Sergio\", \"Oller\", role = \"ctb\"), person(given = \"Posit Software, PBC\", role = c(\"cph\", \"fnd\")), person(, \"jQuery UI contributors\", role = c(\"ctb\", \"cph\"), comment = \"jQuery UI library; authors listed in inst/rmd/h/jqueryui/AUTHORS.txt\"), person(\"Mark\", \"Otto\", role = \"ctb\", comment = \"Bootstrap library\"), person(\"Jacob\", \"Thornton\", role = \"ctb\", comment = \"Bootstrap library\"), person(, \"Bootstrap contributors\", role = \"ctb\", comment = \"Bootstrap library\"), person(, \"Twitter, Inc\", role = \"cph\", comment = \"Bootstrap library\"), person(\"Alexander\", \"Farkas\", role = c(\"ctb\", \"cph\"), comment = \"html5shiv library\"), person(\"Scott\", \"Jehl\", role = c(\"ctb\", \"cph\"), comment = \"Respond.js library\"), person(\"Ivan\", \"Sagalaev\", role = c(\"ctb\", \"cph\"), comment = \"highlight.js library\"), person(\"Greg\", \"Franko\", role = c(\"ctb\", \"cph\"), comment = \"tocify library\"), person(\"John\", \"MacFarlane\", role = c(\"ctb\", \"cph\"), comment = \"Pandoc templates\"), person(, \"Google, Inc.\", role = c(\"ctb\", \"cph\"), comment = \"ioslides library\"), person(\"Dave\", \"Raggett\", role = \"ctb\", comment = \"slidy library\"), person(, \"W3C\", role = \"cph\", comment = \"slidy library\"), person(\"Dave\", \"Gandy\", role = c(\"ctb\", \"cph\"), comment = \"Font-Awesome\"), person(\"Ben\", \"Sperry\", role = \"ctb\", comment = \"Ionicons\"), person(, \"Drifty\", role = \"cph\", comment = \"Ionicons\"), person(\"Aidan\", \"Lister\", role = c(\"ctb\", \"cph\"), comment = \"jQuery StickyTabs\"), person(\"Benct Philip\", \"Jonsson\", role = c(\"ctb\", \"cph\"), comment = \"pagebreak Lua filter\"), person(\"Albert\", \"Krewinkel\", role = c(\"ctb\", \"cph\"), comment = \"pagebreak Lua filter\") )", 820 | "Description": "Convert R Markdown documents into a variety of formats.", 821 | "License": "GPL-3", 822 | "URL": "https://github.com/rstudio/rmarkdown, https://pkgs.rstudio.com/rmarkdown/", 823 | "BugReports": "https://github.com/rstudio/rmarkdown/issues", 824 | "Depends": [ 825 | "R (>= 3.0)" 826 | ], 827 | "Imports": [ 828 | "bslib (>= 0.2.5.1)", 829 | "evaluate (>= 0.13)", 830 | "fontawesome (>= 0.5.0)", 831 | "htmltools (>= 0.5.1)", 832 | "jquerylib", 833 | "jsonlite", 834 | "knitr (>= 1.43)", 835 | "methods", 836 | "tinytex (>= 0.31)", 837 | "tools", 838 | "utils", 839 | "xfun (>= 0.36)", 840 | "yaml (>= 2.1.19)" 841 | ], 842 | "Suggests": [ 843 | "digest", 844 | "dygraphs", 845 | "fs", 846 | "rsconnect", 847 | "downlit (>= 0.4.0)", 848 | "katex (>= 1.4.0)", 849 | "sass (>= 0.4.0)", 850 | "shiny (>= 1.6.0)", 851 | "testthat (>= 3.0.3)", 852 | "tibble", 853 | "vctrs", 854 | "cleanrmd", 855 | "withr (>= 2.4.2)", 856 | "xml2" 857 | ], 858 | "VignetteBuilder": "knitr", 859 | "Config/Needs/website": "rstudio/quillt, pkgdown", 860 | "Config/testthat/edition": "3", 861 | "Encoding": "UTF-8", 862 | "RoxygenNote": "7.3.2", 863 | "SystemRequirements": "pandoc (>= 1.14) - http://pandoc.org", 864 | "NeedsCompilation": "no", 865 | "Author": "JJ Allaire [aut], Yihui Xie [aut, cre] (), Christophe Dervieux [aut] (), Jonathan McPherson [aut], Javier Luraschi [aut], Kevin Ushey [aut], Aron Atkins [aut], Hadley Wickham [aut], Joe Cheng [aut], Winston Chang [aut], Richard Iannone [aut] (), Andrew Dunning [ctb] (), Atsushi Yasumoto [ctb, cph] (, Number sections Lua filter), Barret Schloerke [ctb], Carson Sievert [ctb] (), Devon Ryan [ctb] (), Frederik Aust [ctb] (), Jeff Allen [ctb], JooYoung Seo [ctb] (), Malcolm Barrett [ctb], Rob Hyndman [ctb], Romain Lesur [ctb], Roy Storey [ctb], Ruben Arslan [ctb], Sergio Oller [ctb], Posit Software, PBC [cph, fnd], jQuery UI contributors [ctb, cph] (jQuery UI library; authors listed in inst/rmd/h/jqueryui/AUTHORS.txt), Mark Otto [ctb] (Bootstrap library), Jacob Thornton [ctb] (Bootstrap library), Bootstrap contributors [ctb] (Bootstrap library), Twitter, Inc [cph] (Bootstrap library), Alexander Farkas [ctb, cph] (html5shiv library), Scott Jehl [ctb, cph] (Respond.js library), Ivan Sagalaev [ctb, cph] (highlight.js library), Greg Franko [ctb, cph] (tocify library), John MacFarlane [ctb, cph] (Pandoc templates), Google, Inc. [ctb, cph] (ioslides library), Dave Raggett [ctb] (slidy library), W3C [cph] (slidy library), Dave Gandy [ctb, cph] (Font-Awesome), Ben Sperry [ctb] (Ionicons), Drifty [cph] (Ionicons), Aidan Lister [ctb, cph] (jQuery StickyTabs), Benct Philip Jonsson [ctb, cph] (pagebreak Lua filter), Albert Krewinkel [ctb, cph] (pagebreak Lua filter)", 866 | "Maintainer": "Yihui Xie ", 867 | "Repository": "RSPM" 868 | }, 869 | "sass": { 870 | "Package": "sass", 871 | "Version": "0.4.10", 872 | "Source": "Repository", 873 | "Type": "Package", 874 | "Title": "Syntactically Awesome Style Sheets ('Sass')", 875 | "Description": "An 'SCSS' compiler, powered by the 'LibSass' library. With this, R developers can use variables, inheritance, and functions to generate dynamic style sheets. The package uses the 'Sass CSS' extension language, which is stable, powerful, and CSS compatible.", 876 | "Authors@R": "c( person(\"Joe\", \"Cheng\", , \"joe@rstudio.com\", \"aut\"), person(\"Timothy\", \"Mastny\", , \"tim.mastny@gmail.com\", \"aut\"), person(\"Richard\", \"Iannone\", , \"rich@rstudio.com\", \"aut\", comment = c(ORCID = \"0000-0003-3925-190X\")), person(\"Barret\", \"Schloerke\", , \"barret@rstudio.com\", \"aut\", comment = c(ORCID = \"0000-0001-9986-114X\")), person(\"Carson\", \"Sievert\", , \"carson@rstudio.com\", c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-4958-2844\")), person(\"Christophe\", \"Dervieux\", , \"cderv@rstudio.com\", c(\"ctb\"), comment = c(ORCID = \"0000-0003-4474-2498\")), person(family = \"RStudio\", role = c(\"cph\", \"fnd\")), person(family = \"Sass Open Source Foundation\", role = c(\"ctb\", \"cph\"), comment = \"LibSass library\"), person(\"Greter\", \"Marcel\", role = c(\"ctb\", \"cph\"), comment = \"LibSass library\"), person(\"Mifsud\", \"Michael\", role = c(\"ctb\", \"cph\"), comment = \"LibSass library\"), person(\"Hampton\", \"Catlin\", role = c(\"ctb\", \"cph\"), comment = \"LibSass library\"), person(\"Natalie\", \"Weizenbaum\", role = c(\"ctb\", \"cph\"), comment = \"LibSass library\"), person(\"Chris\", \"Eppstein\", role = c(\"ctb\", \"cph\"), comment = \"LibSass library\"), person(\"Adams\", \"Joseph\", role = c(\"ctb\", \"cph\"), comment = \"json.cpp\"), person(\"Trifunovic\", \"Nemanja\", role = c(\"ctb\", \"cph\"), comment = \"utf8.h\") )", 877 | "License": "MIT + file LICENSE", 878 | "URL": "https://rstudio.github.io/sass/, https://github.com/rstudio/sass", 879 | "BugReports": "https://github.com/rstudio/sass/issues", 880 | "Encoding": "UTF-8", 881 | "RoxygenNote": "7.3.2", 882 | "SystemRequirements": "GNU make", 883 | "Imports": [ 884 | "fs (>= 1.2.4)", 885 | "rlang (>= 0.4.10)", 886 | "htmltools (>= 0.5.1)", 887 | "R6", 888 | "rappdirs" 889 | ], 890 | "Suggests": [ 891 | "testthat", 892 | "knitr", 893 | "rmarkdown", 894 | "withr", 895 | "shiny", 896 | "curl" 897 | ], 898 | "VignetteBuilder": "knitr", 899 | "Config/testthat/edition": "3", 900 | "NeedsCompilation": "yes", 901 | "Author": "Joe Cheng [aut], Timothy Mastny [aut], Richard Iannone [aut] (), Barret Schloerke [aut] (), Carson Sievert [aut, cre] (), Christophe Dervieux [ctb] (), RStudio [cph, fnd], Sass Open Source Foundation [ctb, cph] (LibSass library), Greter Marcel [ctb, cph] (LibSass library), Mifsud Michael [ctb, cph] (LibSass library), Hampton Catlin [ctb, cph] (LibSass library), Natalie Weizenbaum [ctb, cph] (LibSass library), Chris Eppstein [ctb, cph] (LibSass library), Adams Joseph [ctb, cph] (json.cpp), Trifunovic Nemanja [ctb, cph] (utf8.h)", 902 | "Maintainer": "Carson Sievert ", 903 | "Repository": "CRAN" 904 | }, 905 | "tinytex": { 906 | "Package": "tinytex", 907 | "Version": "0.57", 908 | "Source": "Repository", 909 | "Type": "Package", 910 | "Title": "Helper Functions to Install and Maintain TeX Live, and Compile LaTeX Documents", 911 | "Authors@R": "c( person(\"Yihui\", \"Xie\", role = c(\"aut\", \"cre\", \"cph\"), email = \"xie@yihui.name\", comment = c(ORCID = \"0000-0003-0645-5666\")), person(given = \"Posit Software, PBC\", role = c(\"cph\", \"fnd\")), person(\"Christophe\", \"Dervieux\", role = \"ctb\", comment = c(ORCID = \"0000-0003-4474-2498\")), person(\"Devon\", \"Ryan\", role = \"ctb\", email = \"dpryan79@gmail.com\", comment = c(ORCID = \"0000-0002-8549-0971\")), person(\"Ethan\", \"Heinzen\", role = \"ctb\"), person(\"Fernando\", \"Cagua\", role = \"ctb\"), person() )", 912 | "Description": "Helper functions to install and maintain the 'LaTeX' distribution named 'TinyTeX' (), a lightweight, cross-platform, portable, and easy-to-maintain version of 'TeX Live'. This package also contains helper functions to compile 'LaTeX' documents, and install missing 'LaTeX' packages automatically.", 913 | "Imports": [ 914 | "xfun (>= 0.48)" 915 | ], 916 | "Suggests": [ 917 | "testit", 918 | "rstudioapi" 919 | ], 920 | "License": "MIT + file LICENSE", 921 | "URL": "https://github.com/rstudio/tinytex", 922 | "BugReports": "https://github.com/rstudio/tinytex/issues", 923 | "Encoding": "UTF-8", 924 | "RoxygenNote": "7.3.2", 925 | "NeedsCompilation": "no", 926 | "Author": "Yihui Xie [aut, cre, cph] (), Posit Software, PBC [cph, fnd], Christophe Dervieux [ctb] (), Devon Ryan [ctb] (), Ethan Heinzen [ctb], Fernando Cagua [ctb]", 927 | "Maintainer": "Yihui Xie ", 928 | "Repository": "CRAN" 929 | }, 930 | "xfun": { 931 | "Package": "xfun", 932 | "Version": "0.52", 933 | "Source": "Repository", 934 | "Type": "Package", 935 | "Title": "Supporting Functions for Packages Maintained by 'Yihui Xie'", 936 | "Authors@R": "c( person(\"Yihui\", \"Xie\", role = c(\"aut\", \"cre\", \"cph\"), email = \"xie@yihui.name\", comment = c(ORCID = \"0000-0003-0645-5666\", URL = \"https://yihui.org\")), person(\"Wush\", \"Wu\", role = \"ctb\"), person(\"Daijiang\", \"Li\", role = \"ctb\"), person(\"Xianying\", \"Tan\", role = \"ctb\"), person(\"Salim\", \"Brüggemann\", role = \"ctb\", email = \"salim-b@pm.me\", comment = c(ORCID = \"0000-0002-5329-5987\")), person(\"Christophe\", \"Dervieux\", role = \"ctb\"), person() )", 937 | "Description": "Miscellaneous functions commonly used in other packages maintained by 'Yihui Xie'.", 938 | "Depends": [ 939 | "R (>= 3.2.0)" 940 | ], 941 | "Imports": [ 942 | "grDevices", 943 | "stats", 944 | "tools" 945 | ], 946 | "Suggests": [ 947 | "testit", 948 | "parallel", 949 | "codetools", 950 | "methods", 951 | "rstudioapi", 952 | "tinytex (>= 0.30)", 953 | "mime", 954 | "litedown (>= 0.4)", 955 | "commonmark", 956 | "knitr (>= 1.50)", 957 | "remotes", 958 | "pak", 959 | "curl", 960 | "xml2", 961 | "jsonlite", 962 | "magick", 963 | "yaml", 964 | "qs" 965 | ], 966 | "License": "MIT + file LICENSE", 967 | "URL": "https://github.com/yihui/xfun", 968 | "BugReports": "https://github.com/yihui/xfun/issues", 969 | "Encoding": "UTF-8", 970 | "RoxygenNote": "7.3.2", 971 | "VignetteBuilder": "litedown", 972 | "NeedsCompilation": "yes", 973 | "Author": "Yihui Xie [aut, cre, cph] (, https://yihui.org), Wush Wu [ctb], Daijiang Li [ctb], Xianying Tan [ctb], Salim Brüggemann [ctb] (), Christophe Dervieux [ctb]", 974 | "Maintainer": "Yihui Xie ", 975 | "Repository": "CRAN" 976 | }, 977 | "yaml": { 978 | "Package": "yaml", 979 | "Version": "2.3.10", 980 | "Source": "Repository", 981 | "Type": "Package", 982 | "Title": "Methods to Convert R Data to YAML and Back", 983 | "Date": "2024-07-22", 984 | "Suggests": [ 985 | "RUnit" 986 | ], 987 | "Author": "Shawn P Garbett [aut], Jeremy Stephens [aut, cre], Kirill Simonov [aut], Yihui Xie [ctb], Zhuoer Dong [ctb], Hadley Wickham [ctb], Jeffrey Horner [ctb], reikoch [ctb], Will Beasley [ctb], Brendan O'Connor [ctb], Gregory R. Warnes [ctb], Michael Quinn [ctb], Zhian N. Kamvar [ctb], Charlie Gao [ctb]", 988 | "Maintainer": "Shawn Garbett ", 989 | "License": "BSD_3_clause + file LICENSE", 990 | "Description": "Implements the 'libyaml' 'YAML' 1.1 parser and emitter () for R.", 991 | "URL": "https://github.com/vubiostat/r-yaml/", 992 | "BugReports": "https://github.com/vubiostat/r-yaml/issues", 993 | "NeedsCompilation": "yes", 994 | "Repository": "RSPM", 995 | "Encoding": "UTF-8" 996 | } 997 | } 998 | } 999 | -------------------------------------------------------------------------------- /renv/profiles/lesson-requirements/renv/.gitignore: -------------------------------------------------------------------------------- 1 | library/ 2 | local/ 3 | cellar/ 4 | lock/ 5 | python/ 6 | sandbox/ 7 | staging/ 8 | -------------------------------------------------------------------------------- /renv/profiles/lesson-requirements/renv/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "bioconductor.version": null, 3 | "external.libraries": [], 4 | "ignored.packages": [], 5 | "package.dependency.fields": [ 6 | "Imports", 7 | "Depends", 8 | "LinkingTo" 9 | ], 10 | "ppm.enabled": null, 11 | "ppm.ignored.urls": [], 12 | "r.version": null, 13 | "snapshot.type": "implicit", 14 | "use.cache": true, 15 | "vcs.ignore.cellar": true, 16 | "vcs.ignore.library": true, 17 | "vcs.ignore.local": true, 18 | "vcs.manage.ignores": true 19 | } 20 | -------------------------------------------------------------------------------- /setup-python-workshop.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setup for Python workshops 3 | --- 4 | 5 | ## Software 6 | 7 | | Software | Install | Manual | Available for | Description | 8 | | ------------------- | ------------------------------- | ------ | --------------------- | --------------------------------------------------------- | 9 | | Spreadsheet program | [Link](https://www.libreoffice.org/download/download/) | [Link](https://documentation.libreoffice.org/en/english-documentation/) | Linux, MacOS, Windows | Spreadsheet program for organizing tabular data. | 10 | | OpenRefine | [Link](http://openrefine.org/download.html) | [Link](http://openrefine.org/documentation.html) | Linux, MacOS, Windows | Program for reproducibly cleaning data. | 11 | | Python | See install instructions below. | | Linux, MacOS, Windows | Programming language for data analysis and visualisation. | 12 | | SQLite Browser | [Link](http://sqlitebrowser.org/dl/) | [Link](https://github.com/sqlitebrowser/sqlitebrowser/wiki) | Linux, MacOS, Windows | Tool for creating, designing, and editing database files. | 13 | 14 | ```{r include-setup-python, child="files/setup-python.md"} 15 | ``` 16 | 17 | ```{r include-setup-sql, child="files/setup-sql.md"} 18 | ``` 19 | 20 | ```{r include-setup-data, child="files/setup-data.md"} 21 | ``` 22 | 23 | ```{r include-setup-spreadsheet, child="files/setup-spreadsheet.md"} 24 | ``` 25 | 26 | ```{r include-setup-openrefine, child="files/setup-openrefine.md"} 27 | ``` 28 | 29 | Congratulations! You are now ready for the workshop! 30 | 31 | 32 | -------------------------------------------------------------------------------- /setup-r-workshop.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setup for R workshops 3 | --- 4 | 5 | ```{r include-setup-r, child="files/setup-r.md"} 6 | ``` 7 | 8 | ## Software 9 | 10 | | Software | Install | Manual | Available for | Description | 11 | | ------------------- | ------------------------------- | ------ | --------------------- | --------------------------------------------------------- | 12 | | Spreadsheet program | [Link](https://www.libreoffice.org/download/download/) | [Link](https://documentation.libreoffice.org/en/english-documentation/) | Linux, MacOS, Windows | Spreadsheet program for organizing tabular data. | 13 | | OpenRefine | [Link](http://openrefine.org/download.html) | [Link](http://openrefine.org/documentation.html) | Linux, MacOS, Windows | Program for reproducibly cleaning data. | 14 | | R | See install instructions below. | | Linux, MacOS, Windows | Programming language for data analysis and visualisation. | 15 | | RStudio | [Link](https://www.rstudio.com/products/rstudio/download/#download) | [Cheatsheet](https://github.com/rstudio/cheatsheets/raw/master/rstudio-ide.pdf) | Linux, MacOS, Windows | Integrated development environment for R. | 16 | | SQLite Browser | [Link](http://sqlitebrowser.org/dl/) | [Link](https://github.com/sqlitebrowser/sqlitebrowser/wiki) | Linux, MacOS, Windows | Tool for creating, designing, and editing database files. | 17 | 18 | ```{r include-setup-sql, child="files/setup-sql.md"} 19 | ``` 20 | 21 | ```{r include-setup-data, child="files/setup-data.md"} 22 | ``` 23 | 24 | ```{r include-setup-spreadsheet, child="files/setup-spreadsheet.md"} 25 | ``` 26 | 27 | ```{r include-setup-openrefine, child="files/setup-openrefine.md"} 28 | ``` 29 | 30 | Congratulations! You are now ready for the workshop! 31 | 32 | 33 | -------------------------------------------------------------------------------- /site/README.md: -------------------------------------------------------------------------------- 1 | This directory contains rendered lesson materials. Please do not edit files 2 | here. 3 | --------------------------------------------------------------------------------