Merge branch 'main' into main

This commit is contained in:
Benedikt Ehinger 2023-10-06 10:42:43 +02:00 committed by GitHub
commit 12a1a1beb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1655 additions and 586 deletions

View File

@ -0,0 +1,8 @@
title: Downloadthis
author: Shafayet Khan Shafee
version: 1.1.0
quarto-required: ">=1.2.0"
contributes:
shortcodes:
- downloadthis.lua

View File

@ -0,0 +1,121 @@
--[[
MIT License
Copyright (c) 2023 Shafayet Khan Shafee
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]--
local str = pandoc.utils.stringify
--local p = quarto.log.output
local function ensureHtmlDeps()
quarto.doc.add_html_dependency({
name = "downloadthis",
version = "1.9.1",
stylesheets = {"resources/css/downloadthis.css"}
})
end
local function optional(arg, default)
if arg == nil or arg == ""
then
return default
else
return arg
end
end
function import(script)
local path = PANDOC_SCRIPT_FILE:match("(.*[/\\])")
package.path = path .. script .. ";" .. package.path
return require(script)
end
local puremagic = import("puremagic.lua")
return {
['downloadthis'] = function(args, kwargs, meta)
-- args and kwargs
local file_path = str(args[1])
local extension = "." .. file_path:match("[^.]+$")
local dname = optional(str(kwargs["dname"]), "file")
local dfilename = dname .. extension
local btn_label = " " .. optional(str(kwargs["label"]), "Download") .. " "
local btn_type = optional(str(kwargs["type"]), "default")
local icon = optional(str(kwargs["icon"]), "download")
local class = " " .. optional(str(kwargs["class"]), "")
local rand = "dnldts" .. str(math.random(1, 65000))
local id = optional(str(kwargs["id"]), rand)
-- reading files
local fh = io.open(file_path, "rb")
if not fh then
io.stderr:write("Cannot open file " ..
file_path ..
" | Skipping adding buttons\n")
return pandoc.Null()
else
local contents = fh:read("*all")
fh:close()
-- creating dataURI object
local b64_encoded = quarto.base64.encode(contents)
local mimetype = puremagic.via_path(file_path)
local data_uri = 'data:' .. mimetype .. ";base64," .. b64_encoded
-- js code taken from
-- https://github.com/fmmattioni/downloadthis/blob/master/R/utils.R#L59
local js = [[fetch('%s').then(res => res.blob()).then(blob => {
const downloadURL = window.URL.createObjectURL(blob);
const a = document.createElement('a');
document.body.appendChild(a);
a.href = downloadURL;
a.download = '%s'; a.click();
window.URL.revokeObjectURL(downloadURL);
document.body.removeChild(a);
});]]
local clicked = js:format(data_uri, dfilename)
-- creating button
local button =
"<button class=\"btn btn-" .. btn_type .. " downloadthis " ..
class .. "\"" ..
" id=\"" .. id .. "\"" ..
"><i class=\"bi bi-" .. icon .. "\"" .. "></i>" ..
btn_label ..
"</button>"
if quarto.doc.is_format("html:js") and quarto.doc.has_bootstrap()
then
ensureHtmlDeps()
return pandoc.RawInline('html',
"<a href=\"#" .. id .. "\"" ..
" onclick=\"" .. clicked .. "\">" .. button .. "</a>"
)
else
return pandoc.Null()
end
end
end
}

View File

@ -0,0 +1,735 @@
-- puremagic 1.0.1
-- Copyright (c) 2014 Will Bond <will@wbond.net>
-- Licensed under the MIT license.
function basename(path)
local basename_match = path:match('[/\\]([^/\\]+)$')
if basename_match then
return basename_match, nil
end
return path, nil
end
function extension(path)
path = path:lower()
local tar_match = path:match('%.(tar%.[^.]+)$')
if tar_match then
return tar_match
end
if path:sub(#path - 11, #path) == '.numbers.zip' then
return 'numbers.zip'
end
if path:sub(#path - 9, #path) == '.pages.zip' then
return 'pages.zip'
end
if path:sub(#path - 7, #path) == '.key.zip' then
return 'key.zip'
end
return path:match('%.([^.]+)$')
end
function in_table(value, list)
for i=1, #list do
if list[i] == value then
return true
end
end
return false
end
function string_to_bit_table(chars)
local output = {}
for char in chars:gmatch('.') do
local num = string.byte(char)
local bits = {0, 0, 0, 0, 0, 0, 0, 0}
for bit=8, 1, -1 do
if num > 0 then
bits[bit] = math.fmod(num, 2)
num = (num - bits[bit]) / 2
end
end
table.insert(output, bits)
end
return output
end
function bit_table_to_string(bits)
local output = {}
for i = 1, #bits do
local num = tonumber(table.concat(bits[i]), 2)
table.insert(output, string.format('%c', num))
end
return table.concat(output)
end
function bitwise_and(a, b)
local a_bytes = string_to_bit_table(a)
local b_bytes = string_to_bit_table(b)
local output = {}
for i = 1, #a_bytes do
local bits = {0, 0, 0, 0, 0, 0, 0, 0}
for j = 1, 8 do
if a_bytes[i][j] == 1 and b_bytes[i][j] == 1 then
bits[j] = 1
else
bits[j] = 0
end
end
table.insert(output, bits)
end
return bit_table_to_string(output)
end
-- Unpack a little endian byte string into an integer
function unpack_le(chars)
local bit_table = string_to_bit_table(chars)
-- Merge the bits into a string of 1s and 0s
local result = {}
for i=1, #bit_table do
result[#chars + 1 - i] = table.concat(bit_table[i])
end
return tonumber(table.concat(result), 2)
end
-- Unpack a big endian byte string into an integer
function unpack_be(chars)
local bit_table = string_to_bit_table(chars)
-- Merge the bits into a string of 1s and 0s
for i=1, #bit_table do
bit_table[i] = table.concat(bit_table[i])
end
return tonumber(table.concat(bit_table), 2)
end
-- Takes the first 4-8k of an EBML file and identifies if it is matroska or webm
-- and it it contains just video or just audio.
function ebml_parse(content)
local position = 1
local length = #content
local header_token, header_value, used_bytes = ebml_parse_section(content)
position = position + used_bytes
if header_token ~= '\x1AE\xDF\xA3' then
return nil, 'Unable to find EBML ID'
end
-- The matroska spec sets the default doctype to be 'matroska', however
-- many file specify this anyway. The other option is 'webm'.
local doctype = 'matroska'
if header_value['B\x82'] then
doctype = header_value['B\x82']
end
if doctype ~= 'matroska' and doctype ~= 'webm' then
return nil, 'Unknown EBML doctype'
end
local segment_position = nil
local track_position = nil
local has_video = false
local found_tracks = false
while position <= length do
local ebml_id, ebml_value, used_bytes = ebml_parse_section(content:sub(position, length))
position = position + used_bytes
-- Segment
if ebml_id == '\x18S\x80g' then
segment_position = position
end
-- Meta seek information
if ebml_id == '\x11M\x9Bt' then
-- Look for the seek info about the tracks token
for i, child in ipairs(ebml_value['M\xBB']) do
if child['S\xAB'] == '\x16T\xAEk' then
track_position = segment_position + unpack_be(child['S\xAC'])
position = track_position
break
end
end
end
-- Track
if ebml_id == '\x16T\xAEk' then
found_tracks = true
-- Scan through each track looking for video
for i, child in ipairs(ebml_value['\xAE']) do
-- Look to see if the track type is video
if unpack_be(child['\x83']) == 1 then
has_video = true
break
end
end
break
end
end
if found_tracks and not has_video then
if doctype == 'matroska' then
return 'audio/x-matroska'
else
return 'audio/webm'
end
end
if doctype == 'matroska' then
return 'video/x-matroska'
else
return 'video/webm'
end
end
-- Parses a section of an EBML document, returning the EBML ID at the beginning,
-- plus the value as a table with child EBML IDs as keys and the number of
-- bytes from the content that contained the ID and value
function ebml_parse_section(content)
local ebml_id, element_length, used_bytes = ebml_id_and_length(content)
-- Don't parse the segment since it is the whole file!
if ebml_id == '\x18\x53\x80\x67' then
return ebml_id, nil, used_bytes
end
local ebml_value = content:sub(used_bytes + 1, used_bytes + element_length)
used_bytes = used_bytes + element_length
-- We always parse the return value of level 0/1 elements
local recursive_parse = false
if #ebml_id == 4 then
recursive_parse = true
-- We need Seek information
elseif ebml_id == '\x4D\xBB' then
recursive_parse = true
-- We want the top-level of TrackEntry to grab the TrackType
elseif ebml_id == '\xAE' then
recursive_parse = true
end
if recursive_parse then
local buffer = ebml_value
ebml_value = {}
-- Track which child entries have been converted to an array
local array_children = {}
while #buffer > 0 do
local child_ebml_id, child_ebml_value, child_used_bytes = ebml_parse_section(buffer)
if array_children[child_ebml_id] then
table.insert(ebml_value[child_ebml_id], child_ebml_value)
-- Single values are just stores by themselves
elseif ebml_value[child_ebml_id] == nil then
-- Force seek info and tracks to be arrays even if there is only one
if child_ebml_id == 'M\xBB' or child_ebml_id == '\xAE' then
child_ebml_value = {child_ebml_value}
array_children[child_ebml_id] = true
end
ebml_value[child_ebml_id] = child_ebml_value
-- If there is already a value for the ID, turn it into a table
else
ebml_value[child_ebml_id] = {ebml_value[child_ebml_id], child_ebml_value}
array_children[child_ebml_id] = true
end
-- Move past the part we've parsed
buffer = buffer:sub(child_used_bytes + 1, #buffer)
end
end
return ebml_id, ebml_value, used_bytes
end
-- Should accept 12+ bytes, will return the ebml id, the data length and the
-- number of bytes that were used to hold those values.
function ebml_id_and_length(chars)
-- The ID is encoded the same way as the length, however, we don't want
-- to remove the length bits from the ID value or intepret it as an
-- unsigned int since all of the documentation online references the IDs in
-- encoded form.
local _, id_length = ebml_length(chars:sub(1, 4))
local ebml_id = chars:sub(1, id_length)
local remaining = chars:sub(id_length + 1, id_length + 8)
local element_length, used_bytes = ebml_length(remaining)
return ebml_id, element_length, id_length + used_bytes
end
-- Should accept 8+ bytes, will return the data length plus the number of bytes
-- that were used to hold the data length.
function ebml_length(chars)
-- We substring chars to ensure we don't build a huge table we don't need
local bit_tables = string_to_bit_table(chars:sub(1, 8))
local value_length = 1
for i=1, #bit_tables[1] do
if bit_tables[1][i] == 0 then
value_length = value_length + 1
else
-- Clear the indicator bit so the rest of the byte
bit_tables[1][i] = 0
break
end
end
local bits = {}
for i=1, value_length do
table.insert(bits, table.concat(bit_tables[i]))
end
return tonumber(table.concat(bits), 2), value_length
end
function binary_tests(content, ext)
local length = #content
local _1_8 = content:sub(1, 8)
local _1_7 = content:sub(1, 7)
local _1_6 = content:sub(1, 6)
local _1_5 = content:sub(1, 5)
local _1_4 = content:sub(1, 4)
local _1_3 = content:sub(1, 3)
local _1_2 = content:sub(1, 2)
local _9_12 = content:sub(9, 12)
-- Images
if _1_4 == '\xC5\xD0\xD3\xC6' then
-- With a Windows-format EPS, the file starts right after a 30-byte
-- header, or a 30-byte header followed by two bytes of padding
if content:sub(33, 42) == '%!PS-Adobe' or content:sub(31, 40) == '%!PS-Adobe' then
return 'application/postscript'
end
end
if _1_8 == '%!PS-Ado' and content:sub(9, 10) == 'be' then
return 'application/postscript'
end
if _1_4 == 'MM\x00*' or _1_4 == 'II*\x00' then
return 'image/tiff'
end
if _1_8 == '\x89PNG\r\n\x1A\n' then
return 'image/png'
end
if _1_6 == 'GIF87a' or _1_6 == 'GIF89a' then
return 'image/gif'
end
if _1_4 == 'RIFF' and _9_12 == 'WEBP' then
return 'image/webp'
end
if _1_2 == 'BM' and length > 14 and in_table(content:sub(15, 15), {'\x0C', '(', '@', '\x80'}) then
return 'image/x-ms-bmp'
end
local normal_jpeg = length > 10 and in_table(content:sub(7, 10), {'JFIF', 'Exif'})
local photoshop_jpeg = length > 24 and _1_4 == '\xFF\xD8\xFF\xED' and content:sub(21, 24) == '8BIM'
if normal_jpeg or photoshop_jpeg then
return 'image/jpeg'
end
if _1_4 == '8BPS' then
return 'image/vnd.adobe.photoshop'
end
if _1_8 == '\x00\x00\x00\x0CjP ' and _9_12 == '\r\n\x87\n' then
return 'image/jp2'
end
if _1_4 == '\x00\x00\x01\x00' then
return 'application/vnd.microsoft.icon'
end
-- Audio/Video
if _1_4 == '\x1AE\xDF\xA3' and length > 1000 then
local mimetype, err = ebml_parse(content)
if mimetype then
return mimetype
end
end
if _1_4 == 'MOVI' then
if in_table(content:sub(5, 8), {'moov', 'mdat'}) then
return 'video/quicktime'
end
end
if length > 8 and content:sub(5, 8) == 'ftyp' then
local lower_9_12 = _9_12:lower()
if in_table(lower_9_12, {'avc1', 'isom', 'iso2', 'mp41', 'mp42', 'mmp4', 'ndsc', 'ndsh', 'ndsm', 'ndsp', 'ndss', 'ndxc', 'ndxh', 'ndxm', 'ndxp', 'ndxs', 'f4v ', 'f4p ', 'm4v '}) then
return 'video/mp4'
end
if in_table(lower_9_12, {'msnv', 'ndas', 'f4a ', 'f4b ', 'm4a ', 'm4b ', 'm4p '}) then
return 'audio/mp4'
end
if in_table(lower_9_12, {'3g2a', '3g2b', '3g2c', 'kddi'}) then
return 'video/3gpp2'
end
if in_table(lower_9_12, {'3ge6', '3ge7', '3gg6', '3gp1', '3gp2', '3gp3', '3gp4', '3gp5', '3gp6', '3gs7'}) then
return 'video/3gpp'
end
if lower_9_12 == 'mqt ' or lower_9_12 == 'qt ' then
return 'video/quicktime'
end
if lower_9_12 == 'jp2 ' then
return 'image/jp2'
end
end
-- MP3
if bitwise_and(_1_2, '\xFF\xF6') == '\xFF\xF2' then
local byte_3 = content:sub(3, 3)
if bitwise_and(byte_3, '\xF0') ~= '\xF0' and bitwise_and(byte_3, "\x0C") ~= "\x0C" then
return 'audio/mpeg'
end
end
if _1_3 == 'ID3' then
return 'audio/mpeg'
end
if _1_4 == 'fLaC' then
return 'audio/x-flac'
end
if _1_8 == '0&\xB2u\x8Ef\xCF\x11' then
-- Without writing a full-on ASF parser, we can just scan for the
-- UTF-16 string "AspectRatio"
if content:find('\x00A\x00s\x00p\x00e\x00c\x00t\x00R\x00a\x00t\x00i\x00o', 1, true) then
return 'video/x-ms-wmv'
end
return 'audio/x-ms-wma'
end
if _1_4 == 'RIFF' and _9_12 == 'AVI ' then
return 'video/x-msvideo'
end
if _1_4 == 'RIFF' and _9_12 == 'WAVE' then
return 'audio/x-wav'
end
if _1_4 == 'FORM' and _9_12 == 'AIFF' then
return 'audio/x-aiff'
end
if _1_4 == 'OggS' then
local _29_33 = content:sub(29, 33)
if _29_33 == '\x01vorb' then
return 'audio/vorbis'
end
if _29_33 == '\x07FLAC' then
return 'audio/x-flac'
end
if _29_33 == 'OpusH' then
return 'audio/ogg'
end
-- Theora and OGM
if _29_33 == '\x80theo' or _29_33 == 'vide' then
return 'video/ogg'
end
end
if _1_3 == 'FWS' or _1_3 == 'CWS' then
return 'application/x-shockwave-flash'
end
if _1_3 == 'FLV' then
return 'video/x-flv'
end
if _1_5 == '%PDF-' then
return 'application/pdf'
end
if _1_5 == '{\\rtf' then
return 'text/rtf'
end
-- Office '97-2003 formats
if _1_8 == '\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1' then
if in_table(ext, {'xls', 'csv', 'tab'}) then
return 'application/vnd.ms-excel'
end
if ext == 'ppt' then
return 'application/vnd.ms-powerpoint'
end
-- We default to word since we need something if the extension isn't recognized
return 'application/msword'
end
if _1_8 == '\x09\x04\x06\x00\x00\x00\x10\x00' then
return 'application/vnd.ms-excel'
end
if _1_6 == '\xDB\xA5\x2D\x00\x00\x00' or _1_5 == '\x50\x4F\x5E\x51\x60' or _1_4 == '\xFE\x37\x00\x23' or _1_3 == '\x94\xA6\x2E' then
return 'application/msword'
end
if _1_4 == 'PK\x03\x04' then
-- Office XML formats
if ext == 'xlsx' then
return 'application/vnd.ms-excel'
end
if ext == 'pptx' then
return 'application/vnd.ms-powerpoint'
end
if ext == 'docx' then
return 'application/msword'
end
-- Open Office formats
if ext == 'ods' then
return 'application/vnd.oasis.opendocument.spreadsheet'
end
if ext == 'odp' then
return 'application/vnd.oasis.opendocument.presentation'
end
if ext == 'odt' then
return 'application/vnd.oasis.opendocument.text'
end
-- iWork - some programs like Mac Mail change the filename to
-- .numbers.zip, etc
if ext == 'pages' or ext == 'pages.zip' then
return 'application/vnd.apple.pages'
end
if ext == 'key' or ext == 'key.zip' then
return 'application/vnd.apple.keynote'
end
if ext == 'numbers' or ext == 'numbers.zip' then
return 'application/vnd.apple.numbers'
end
-- Otherwise just a zip
return 'application/zip'
end
-- Archives
if length > 257 then
if content:sub(258, 263) == 'ustar\x00' then
return 'application/x-tar'
end
if content:sub(258, 265) == 'ustar\x40\x40\x00' then
return 'application/x-tar'
end
end
if _1_7 == 'Rar!\x1A\x07\x00' or _1_8 == 'Rar!\x1A\x07\x01\x00' then
return 'application/x-rar-compressed'
end
if _1_2 == '\x1F\x9D' then
return 'application/x-compress'
end
if _1_2 == '\x1F\x8B' then
return 'application/x-gzip'
end
if _1_3 == 'BZh' then
return 'application/x-bzip2'
end
if _1_6 == '\xFD7zXZ\x00' then
return 'application/x-xz'
end
if _1_6 == '7z\xBC\xAF\x27\x1C' then
return 'application/x-7z-compressed'
end
if _1_2 == 'MZ' then
local pe_header_start = unpack_le(content:sub(61, 64))
local signature = content:sub(pe_header_start + 1, pe_header_start + 4)
if signature == 'PE\x00\x00' then
local image_file_header_start = pe_header_start + 5
local characteristics = content:sub(image_file_header_start + 18, image_file_header_start + 19)
local is_dll = bitwise_and(characteristics, '\x20\x00') == '\x20\x00'
if is_dll then
return 'application/x-msdownload'
end
return 'application/octet-stream'
end
end
return nil
end
function text_tests(content)
local lower_content = content:lower()
if content:find('^%%!PS-Adobe') then
return 'application/postscript'
end
if lower_content:find('<?php', 1, true) or content:find('<?=', 1, true) then
return 'application/x-httpd-php'
end
if lower_content:find('^%s*<%?xml') then
if content:find('<svg') then
return 'image/svg+xml'
end
if lower_content:find('<!doctype html') then
return 'application/xhtml+xml'
end
if content:find('<rss') then
return 'application/rss+xml'
end
return 'application/xml'
end
if lower_content:find('^%s*<html') or lower_content:find('^%s*<!doctype') then
return 'text/html'
end
if lower_content:find('^#![/a-z0-9]+ ?python') then
return 'application/x-python'
end
if lower_content:find('^#![/a-z0-9]+ ?perl') then
return 'application/x-perl'
end
if lower_content:find('^#![/a-z0-9]+ ?ruby') then
return 'application/x-ruby'
end
if lower_content:find('^#![/a-z0-9]+ ?php') then
return 'application/x-httpd-php'
end
if lower_content:find('^#![/a-z0-9]+ ?bash') then
return 'text/x-shellscript'
end
return nil
end
local ext_map = {
css = 'text/css',
csv = 'text/csv',
htm = 'text/html',
html = 'text/html',
xhtml = 'text/html',
ics = 'text/calendar',
js = 'application/javascript',
php = 'application/x-httpd-php',
php3 = 'application/x-httpd-php',
php4 = 'application/x-httpd-php',
php5 = 'application/x-httpd-php',
inc = 'application/x-httpd-php',
pl = 'application/x-perl',
cgi = 'application/x-perl',
py = 'application/x-python',
rb = 'application/x-ruby',
rhtml = 'application/x-ruby',
rss = 'application/rss+xml',
sh = 'text/x-shellscript',
tab = 'text/tab-separated-values',
vcf = 'text/x-vcard',
xml = 'application/xml'
}
function ext_tests(ext)
local mimetype = ext_map[ext]
if mimetype then
return mimetype
end
return 'text/plain'
end
local _M = {}
function _M.via_path(path, filename)
local f, err = io.open(path, 'r')
if not f then
return nil, err
end
local content = f:read(4096)
f:close()
if not filename then
filename = basename(path)
end
return _M.via_content(content, filename)
end
function _M.via_content(content, filename)
local ext = extension(filename)
-- If there are no low ASCII chars and no easily distinguishable tokens,
-- we need to detect by file extension
local mimetype = nil
mimetype = binary_tests(content, ext)
if mimetype then
return mimetype
end
-- Binary-looking files should have been detected so far
if content:find('[%z\x01-\x08\x0B\x0C\x0E-\x1F]') then
return 'application/octet-stream'
end
mimetype = text_tests(content)
if mimetype then
return mimetype
end
return ext_tests(ext)
end
return _M

View File

@ -0,0 +1,13 @@
.downloadthis:focus,
.downloadthis:active {
box-shadow: none !important;
}
.downloadthis:hover {
transition: 0.2s;
filter: brightness(0.90);
}
.downloadthis:active {
filter: brightness(0.80);
}

View File

@ -41,31 +41,33 @@ website:
contents:
- href: material/1_mon/rse/rse_basics_slides.qmd
text: "📊 1 - RSE"
- href: material/1_mon/why_julia/page.qmd
- href: "material/1_mon/why_julia/page.qmd"
text: "📊 2 - Why Julia"
- href: material/1_mon/firststeps/firststeps_handout.qmd
- href: "material/1_mon/firststeps/firststeps_handout.qmd"
text: "📝 3 - First Steps: Handout"
- href: material/1_mon/firststeps/tasks.qmd
- href: "material/1_mon/firststeps/tasks.qmd"
text: "🛠 3 - First Steps: Exercises"
- href: material/1_mon/envs/envs_handout.qmd
- href: "material/1_mon/envs/envs_handout.qmd"
text: "📝 4 - Envs & Pkgs : Handout"
- href: material/1_mon/envs/tasks.qmd
- href: "material/1_mon/envs/tasks.qmd"
text: "🛠 4 - Envs & Pkgs: Exercises"
- section: "Tuesday"
contents:
- href: material/2_tue/git/intro_slides.md
text: "📝 1 - GIT"
- href: material/2_tue/unittest/missing.qmd
- href: material/2_tue/git/slides.md
text: "📝 1 - Advanced Git and Contributing"
- href: "material/2_tue/git/tasks.qmd"
text: "🛠 1 - Git: Exercises"
- href: "material/2_tue/unittest/missing.qmd"
text: "📝 2 - Unit Testing"
- href: material/2_tue/CI/missing.qmd
- href: "material/2_tue/CI/missing.qmd"
text: "📝 3 - Continuous Integration"
- href: material/2_tue/codereview/slides.qmd
text: "📊 4 - Code Review"
text: "📝 4 - Code Review"
- section: "Wednesday"
contents:
- href: material/3_wed/docs/handout.qmd
text: "📝 1 - Docs: Handout"
- href: material/3_wed/docs/tasks.qmd
- href: material/3_wed/docs/tasks.qmd"
text: "🛠 1 - Docs: Exercises"
- href: material/3_wed/vis/handout.qmd
text: "📝 2 - Visualizations: Handout"
@ -73,15 +75,15 @@ website:
text: "🛠 2 - Visualizations: Exercises"
- href: material/3_wed/linalg/slides.qmd
text: "📝 3 - LinearAlgebra"
- href: material/3_wed/regression/missing.jl
- href: material/3_wed/regression/MultipleRegressionBasics.qmd
text: "📝 4 - Multiple Regression"
- section: "Thursday"
contents:
- href: material/4_thu/sim/slides.qmd
text: "📊 1 - Simulation"
text: "📝 1 - Simulation"
- href: material/4_thu/stats/missing.jl
text: "📝 2 - Stats"
text: "📝 2 - Bootstrapping"
- href: material/4_thu/parallel/slides.qmd
text: "📝 3 - Parallelization"
- section: "Friday"
@ -93,11 +95,11 @@ website:
background: primary
page-footer:
background: light
left: "CC-By Ehinger, Oesting, Uekerman"
left: "CC-By Ehinger, Oesting, Uekerman, DeBruine, Ranocha, Szufel"
resources:
- CNAME
keep-ipynb: true
format:
html:
email-obfuscation: javascript
@ -117,4 +119,4 @@ format:
sidebar-width: 400px
code-annotations: hover
margin-header: |
![](https://www.simtech.uni-stuttgart.de/img/events/Summer-School/Zeichenflaeche-3-Kopie-42x.png?__scale=w:150,h:150)
![](https://www.simtech.uni-stuttgart.de/img/events/Summer-School/Zeichenflaeche-3-Kopie-42x.png?__scale=w:150,h:150)

View File

@ -18,6 +18,6 @@ Keep this website ready and have a look at the schedule!
----
We wish you all a interesting, safe and fun summerschool. If there are any interpersonal issues (especially regarding [code-of-conduct](https://www.uni-stuttgart.de/en/university/profile/diversity/code-of-conduct/)), please directly contact [Benedikt Ehinger](benedikt.ehinger@vis.uni-stuttgart.de)^[If there are problem with him, please contact **Marco Oesting**]. For organizational issues, please contact TODO
We wish you all a interesting, safe and fun summerschool. If there are any interpersonal issues (especially regarding [code-of-conduct](https://www.uni-stuttgart.de/en/university/profile/diversity/code-of-conduct/)), please directly contact [Benedikt Ehinger](benedikt.ehinger@vis.uni-stuttgart.de)^[If there are problem with him, please contact **Marco Oesting**]. For organizational issues, please contact [Sina Schorndorfer](sina.schorndorfer@imsb.uni-stuttgart.de)
Best, Benedikt, Benjamin, Marco

View File

@ -21,10 +21,6 @@ VSCode automatically loads the `Revise.jl` package, which screens all your activ
## Syntax differences Python/R/MatLab
### In the beginning there was `nothing`
`nothing`- but also `NaN` and also `Missing`.
Each of those has a specific purpose, but most likely we will only need `a = nothing` and `b = NaN`.
### Control Structures
@ -94,6 +90,14 @@ end
myfunction(args...;kwargs...) = myotherfunction(newarg,args...;kwargs...)
```
### In the beginning there was `nothing`
`nothing`- but also `NaN` and also `Missing`.
Each of those has a specific purpose, but most likely we will only need `a = nothing` and `b = NaN`.
Note that `NaN` counts as a Float-Number, whereas nothing & missing does not.
#### Excourse: splatting & slurping
Think of it as unpacking / collecting something

View File

@ -1,5 +1,8 @@
---
format: revealjs
format:
revealjs:
output-file: rse_basics_slides_revealjs.html
html: default
---
# Introduction to the Research Software Engineering Summerschol
@ -10,6 +13,8 @@ format: revealjs
Find all slides, all materials, and the schedule
([link to presentation](rse_basics_slides_revealjs.html))
## Last minute organization issues
-
@ -20,8 +25,6 @@ Find all slides, all materials, and the schedule
- Check out the schedule
- You will learn to use basic Julia
- In the beginning we will focus on the Research Software Engineering part!
- Advanced Julia, later this week and by request ;)

View File

@ -1,102 +0,0 @@
# Git Demo
## Recap of Git basics
- Expert level poll on git: ask students to estimate their level.
- Beginner: I have hardly ever used Git
- User: pull, commit, push, status, diff
- Developer: fork, branch, merge, checkout
- Maintainer: rebase, squash, cherry-pick, bisect
- Owner: submodules
![git overview picture from py-rse](https://merely-useful.tech/py-rse/figures/git-cmdline/git-remote.png)
- `git --help`, `git commit --help`
- incomplete statement `git comm`
- There is a difference between Git and hosting services ([*forges*](https://en.wikipedia.org/wiki/Forge_(software)))
- [GitHub](https://github.com/)
- [GitLab](https://about.gitlab.com/), open-source, hosted e.g. at [IPVS](https://gitlab-sim.informatik.uni-stuttgart.de)
- [Bitbucket](https://bitbucket.org/product/)
- [SourceForge](https://sourceforge.net/)
- many more
- often, more than just hosting, also DevOps
- Give outlook on remainder of Git chapter: *How I work with Git*, quiz, advanced topics (workflows, rebase, standards), *my neat little Git trick*
## How I work with Git
Starting remarks:
- There is not *the one solution* how to do things with Git. I simply show what I typically use.
- Don't use a client if you don't understand the command line `git`
- (1) Look at GitHub
- [preCICE repository](https://github.com/precice/precice)
- default branch `develop`
- fork -> my fork
- (2) Working directory:
- ZSH shell shows git branches
- `git remote -v` (I have upstream, myfork, ...)
- mention difference between ssh and https (also see GitHub)
- get newest changes `git pull upstream develop`
- `git log` -> I use special format, see `~/.gitconfig`,
- check log on GitHub; explain short hash
- `git branch`
- `git branch add-demo-feature`
- `git checkout add-demo-feature`
- (3) First commit
- `git status` -> always tells you what you can do
- `vi src/action/Action.hpp` -> add `#include "MagicHeader.hpp"`
- `git diff`, `git diff src/com/Action.hpp`, `git diff --color-words`
- `git status`, `git add`, `git status`
- `git commit` -> "Include MagicHeader in Action.hpp"
- `git status`, `git log`, `git log -p`, `git show`
- (4) Change or revert things
- I forgot to add sth: `git reset --soft HEAD~1`, `git status`
- `git diff`, `git diff HEAD` because already staged
- `git log`
- `git commit`
- actually all that is nonsense: `git reset --hard HEAD~1`
- modify again, all nonsense before committing: `git checkout src/action/Action.hpp`
- (5) Stash
- while working on unfinished feature, I need to change / test this other thing quickly, too lazy for commits / branches
- `git stash`
- `git stash pop`
- (6) Create PR
- create commit again
- preview what will be in PR: `git diff develop..add-demo-feature`
- `git push -u myfork add-demo-feature` -> copy link
- explain PR template
- explain target branch
- explain "Allow edits by maintainers"
- cancel
- my fork -> branches -> delete
- (7) Check out someone else's work
- have a look at an existing PR, look at all tabs, show suggestion feature
- but sometimes we want to really build and try sth out ...
- `git remote -v`
- `git remote add alex git@github.com:ajaust/precice.git` if I don't have remote already (or somebody else)
- `git fetch alex`
- `git checkout -t alex/[branch-name]`
- I could now also push to `ajaust`'s remote
## Further reading
### Quick things
- [Video: Git in 15 minutes: basics, branching, no remote](https://www.youtube.com/watch?v=USjZcfj8yxE)
- [The GitHub Blog: Commits are snapshots, not diffs](https://github.blog/2020-12-17-commits-are-snapshots-not-diffs/)
- Chapters [6](https://merely-useful.tech/py-rse/git-cmdline.html) and [7](https://merely-useful.tech/py-rse/git-advanced.html) of Research Software Engineering with Python
- [Podcast All Things Git: History of VC](https://www.allthingsgit.com/episodes/the_history_of_vc_with_eric_sink.html)
- [git purr](https://girliemac.com/blog/2017/12/26/git-purr/)
### References
- [Official documentation](http://git-scm.com/doc)

View File

@ -1,113 +0,0 @@
---
type: slide
slideOptions:
transition: slide
width: 1400
height: 900
margin: 0.1
---
<style>
.reveal strong {
font-weight: bold;
color: orange;
}
.reveal p {
text-align: left;
}
.reveal section h1 {
color: orange;
}
.reveal section h2 {
color: orange;
}
</style>
# Introduction to version control
---
## Learning goals of section
- Refresh and organize students' existing knowledge on Git (learn how to learn more).
- Students can explain difference between merge and rebase and when to use what.
- How to use Git workflows to organize research software development in a team.
- Get to know a few useful GitHub/GitLab standards and a few helpful tools.
---
## Why do we need version control?
Version control ...
- tracks changes to files and helps people share those changes with each other.
- Could also be done via email / Google Docs / ..., but not as accurately and efficiently
- was originally developed for software development, but today cornerstone of *reproducible research*
> "If you can't git diff a file format, it's broken."
---
## How does version control work?
- *master* (or *main*) copy of code in repository, can't edit directly
- Instead: check out a working copy of code, edit, commit changes back
- Repository records complete revision history
- You can go back in time
- It's clear who did what when
---
## The alternative: A story told in file names
<img src="http://phdcomics.com/comics/archive/phd052810s.gif" width=60% style="margin-left:auto; margin-right:auto">
[http://phdcomics.com/comics/archive/phd052810s.gif](http://phdcomics.com/comics/archive/phd052810s.gif)
---
## A very short history of version control I
The old centralized variants:
- 1982: RCS (Revision Control System), operates on single files
- 1986 (release in 1990): CVS (Concurrent Versions System), front end of RCS, operates on whole projects
- 1994: VSS (Microsoft Visual SourceSafe)
- 2000: SVN (Apache Subversion), mostly compatible successor of CVS, *still used today*
---
## A very short history of version control II
Distributed version control:
- Besides remote master version, also local copy of repository
- More memory required, but much better performance
- For a long time: highly fragmented market
- 2000: BitKeeper (originally proprietary software)
- 2005: Mercurial
- 2005: Git
- A few more
Learn more: [Podcast All Things Git: History of VC](https://www.allthingsgit.com/episodes/the_history_of_vc_with_eric_sink.html)
---
## The only standard today: Git
No longer a fragmented market, there is nearly only Git today:
- [Stackoverflow developer survey 2021](https://insights.stackoverflow.com/survey/2021#technology-most-popular-technologies):
> "Over 90% of respondents use Git, suggesting that it is a fundamental tool to being a developer."
- All software project candidates for *contribution challenge* use Git
- Is this good or bad?
---
## More facts on Git
Git itself is open-source: GPL license
- source on [GitHub](https://github.com/git/git), contributions are a bit more complicated than a simple PR
- written mainly in C
- started by Linus Torvalds, core maintainer since later 2005: Junio Hamano

View File

@ -1,148 +0,0 @@
---
type: slide
slideOptions:
transition: slide
width: 1400
height: 900
margin: 0.1
---
<style>
.reveal strong {
font-weight: bold;
color: orange;
}
.reveal p {
text-align: left;
}
.reveal section h1 {
color: orange;
}
.reveal section h2 {
color: orange;
}
.reveal code {
font-family: 'Ubuntu Mono';
color: orange;
}
.reveal section img {
background:none;
border:none;
box-shadow:none;
}
</style>
# Merge vs. Rebase
---
## Linear History
<img src="https://raw.githubusercontent.com/Simulation-Software-Engineering/Lecture-Material/main/01_version_control/figs/history_linear/fig.png" width=60%; style="margin-left:auto; margin-right:auto; padding-top: 25px; padding-bottom: 25px">
- Commits are snapshots + pointer to parent, not diffs
- But for linear history, this makes no difference
- Each normal commit has one parent commit
- `c05f017^` <-- `c05f017`
- `A` = `B^` <-- `B`
- (`^` is the same as `~1`)
- Pointer to parent commit goes into hash
- `git show` gives diff of commit to parent
---
## Merge Commits
- `git checkout main && git merge feature`
<img src="https://raw.githubusercontent.com/Simulation-Software-Engineering/Lecture-Material/main/01_version_control/figs/history_merge/fig.png" width=70%; style="margin-left:auto; margin-right:auto; padding-top: 25px; padding-bottom: 25px" >
- A merge commit (normally) has two parent commits `M^1` and `M^2` (don't confuse `^2` with `~2`)
- Can't show unique diff
- First parent relative to the branch you are on (`M^1` = `C`, `M^2` = `E`)
- `git show`
- `git show`: *"combined diff"*
- GitHub: `git show --first-parent`
- `git show -m`: separate diff to all parents
---
## Why is a Linear History Important?
We use here:
> Linear history := no merge commits
- Merge commits are hard to understand per se.
- A merge takes all commits from `feature` to `main` (on `git log`). --> Hard to understand
- Developers often follow projects by reading commits (reading the diffs). --> Harder to read (where happened what)
- Tracing bugs easier with linear history (see `git bisect`)
- Example: We know a bug was introduced between `v1.3` and `v1.4`.
---
## How to get a Linear History?
- Real conflicts are very rare in real projects, most merge commits are false positives (not conflicts) and should be avoided.
- If there are no changes on `main`, `git merge` does a *"fast-forward"* merge (no merge commit).
- If there are changes on `main`, rebase `feature` branch.
---
## Rebase
- `git checkout feature && git rebase main`
<img src="https://raw.githubusercontent.com/Simulation-Software-Engineering/Lecture-Material/main/01_version_control/figs/history_rebase/fig.png" width=90%; style="margin-left:auto; margin-right:auto; padding-top: 25px; padding-bottom: 25px">
- States of issues change (and new parents) --> history is rewritten
- If `feature` is already on remote, it needs a force push `git push --force myfork feature` (or `--force-with-lease`).
- Be careful: Only use rebase if **only you** work on a branch (a local branch or a branch on your fork).
- For local branches very helpful: `git pull --rebase` (fetch & rebase)
---
## GitHub PR Merge Variants
- GitHub offers three ways to merge a non-conflicting (no changes in same files) PR:
- Create a merge commit
- Squash and merge
- Rebase and merge
- Look at a PR together, e.g. [PR 1432 from preCICE](https://github.com/precice/precice/pull/1432) (will be closed eventually)
> What do the options do?
---
## Squash and Merge
- ... squashes all commits into one
- Often, single commits of feature branch are important while developing the feature,
- ... but not when the feature is merged
- Works well for small feature PRs
- ... also does a rebase (interactively, `git rebase -i`)
---
## Conflicts
> But what if there is a conflict?
- Resolve by rebasing `feature` branch (recommended)
- Or resolve by merging `main` into `feature`
---
## Summary and Final Remarks
- Try to keep a linear history with rebasing whenever reasonable
- Don't use rebase on a public/shared branch during development
- Squash before merging if reasonable
- Delete `feature` branch after merging
- Local view: `git log --graph`
- Remote view on GitHub, e.g. [for preCICE](https://github.com/precice/precice/network)
---
## Further Reading
- [Bitbucket docs: "Merging vs. Rebasing"](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)
- [Hackernoon: "What's the diff?"](https://hackernoon.com/git-merge-vs-rebase-whats-the-diff-76413c117333)
- [GitHub Blog: "Commits are snapshots, not diffs"](https://github.blog/2020-12-17-commits-are-snapshots-not-diffs/)
- [Stack Overflow: "Git show of a merge commit"](https://stackoverflow.com/questions/40986518/git-show-of-a-merge-commit?)

View File

@ -0,0 +1,516 @@
---
type: slide
slideOptions:
transition: slide
width: 1400
height: 900
margin: 0.1
---
<style>
.reveal strong {
font-weight: bold;
color: orange;
}
.reveal p {
text-align: left;
}
.reveal section h1 {
color: orange;
}
.reveal section h2 {
color: orange;
}
.reveal code {
font-family: 'Ubuntu Mono';
color: orange;
}
.reveal section img {
background:none;
border:none;
box-shadow:none;
}
</style>
## Learning Goals of the Git Lecture
- Refresh and organize students' existing knowledge on Git (learn how to learn more).
- Students can explain difference between merge and rebase and when to use what.
- How to use Git workflows to organize research software development in a team.
- Get to know a few useful GitHub/GitLab standards and a few helpful tools.
- Get to know a few rules on good commit messages.
Material is taken and modified from the [SSE lecture](https://github.com/Simulation-Software-Engineering/Lecture-Material), which builds partly on the [py-rse book](https://merely-useful.tech/py-rse).
---
# 1. Introduction to Version Control
---
## Why Do We Need Version Control?
Version control ...
- tracks changes to files and helps people share those changes with each other.
- Could also be done via email / Google Docs / ..., but not as accurately and efficiently
- was originally developed for software development, but today cornerstone of *reproducible research*
> "If you can't git diff a file format, it's broken."
---
## How Does Version Control Work?
- *master* (or *main*) copy of code in repository, can't edit directly
- Instead: check out a working copy of code, edit, commit changes back
- Repository records complete revision history
- You can go back in time
- It's clear who did what when
---
## The Alternative: A Story Told in File Names
<img src="http://phdcomics.com/comics/archive/phd052810s.gif" width=60% style="margin-left:auto; margin-right:auto">
[http://phdcomics.com/comics/archive/phd052810s.gif](http://phdcomics.com/comics/archive/phd052810s.gif)
---
## A Very Short History of Version Control I
The old centralized variants:
- 1982: RCS (Revision Control System), operates on single files
- 1986 (release in 1990): CVS (Concurrent Versions System), front end of RCS, operates on whole projects
- 1994: VSS (Microsoft Visual SourceSafe)
- 2000: SVN (Apache Subversion), mostly compatible successor of CVS, *still used today*
---
## A Very Short History of Version Control II
Distributed version control:
- Besides remote master version, also local copy of repository
- More memory required, but much better performance
- For a long time: highly fragmented market
- 2000: BitKeeper (originally proprietary software)
- 2005: Mercurial
- 2005: Git
- A few more
Learn more: [Podcast All Things Git: History of VC](https://www.allthingsgit.com/episodes/the_history_of_vc_with_eric_sink.html)
---
## The Only Standard Today: Git
No longer a fragmented market, there is nearly only Git today:
- [Stackoverflow developer survey 2021](https://insights.stackoverflow.com/survey/2021#technology-most-popular-technologies):
> "Over 90% of respondents use Git, suggesting that it is a fundamental tool to being a developer."
- Is this good or bad?
---
## More Facts on Git
- Git itself is open-source: GPL license
- Source code on [GitHub](https://github.com/git/git), contributions are a bit more complicated than a simple PR
- Written mainly in C
- Started by Linus Torvalds, core maintainer since later 2005: Junio Hamano
- **Git** (the version control software) vs. **git** (the command line interface)
---
## Forges
There is a difference between Git and hosting services ([*forges*](https://en.wikipedia.org/wiki/Forge_(software))):
- [GitHub](https://github.com/)
- [GitLab](https://about.gitlab.com/), open-source, hosted e.g. at [IPVS](https://gitlab-sim.informatik.uni-stuttgart.de)
- [Bitbucket](https://bitbucket.org/product/)
- [SourceForge](https://sourceforge.net/)
- many more
- often, more than just hosting, also DevOps
---
# 2. Recap of Git Basics
---
## Expert level poll
Which level do you have?
- **Beginner**: hardly ever used Git
- **User**: pull, commit, push, status, diff
- **Developer**: fork, branch, merge, checkout
- **Maintainer**: rebase, squash, cherry-pick, bisect
- **Owner**: submodules
---
## Overview
<img src="https://merely-useful.tech/py-rse/figures/git-cmdline/git-remote.png" width=60% style="margin-left:auto; margin-right:auto">
[Git overview picture from py-rse](https://merely-useful.tech/py-rse/figures/git-cmdline/git-remote.png)
---
## Demo
- `git --help`, `git commit --help`
- incomplete statement `git comm`
- There is not *the one solution* how to do things with Git. I simply show what I typically use.
- Don't use a client if you don't understand the command line `git`
- (1) Look at GitHub
- [preCICE repository](https://github.com/precice/precice)
- default branch `develop`
- fork -> my fork
- (2) Working directory:
- ZSH shell shows git branches
- `git remote -v` (I have upstream, myfork, ...)
- mention difference between ssh and https (also see GitHub)
- get newest changes `git pull upstream develop`
- `git log` -> I use special format, see `~/.gitconfig`,
- check log on GitHub; explain short hash
- `git branch`
- `git branch add-demo-feature`
- `git checkout add-demo-feature`
- (3) First commit
- `git status` -> always tells you what you can do
- `vi src/action/Action.hpp` -> add `#include "MagicHeader.hpp"`
- `git diff`, `git diff src/com/Action.hpp`, `git diff --color-words`
- `git status`, `git add`, `git status`
- `git commit` -> "Include MagicHeader in Action.hpp"
- `git status`, `git log`, `git log -p`, `git show`
- (4) Change or revert things
- I forgot to add sth: `git reset --soft HEAD~1`, `git status`
- `git diff`, `git diff HEAD` because already staged
- `git log`
- `git commit`
- actually all that is nonsense: `git reset --hard HEAD~1`
- modify again, all nonsense before committing: `git checkout src/action/Action.hpp`
- (5) Stash
- while working on unfinished feature, I need to change / test this other thing quickly, too lazy for commits / branches
- `git stash`
- `git stash pop`
- (6) Create PR
- create commit again
- preview what will be in PR: `git diff develop..add-demo-feature`
- `git push -u myfork add-demo-feature` -> copy link
- explain PR template
- explain target branch
- explain "Allow edits by maintainers"
- cancel
- my fork -> branches -> delete
- (7) Check out someone else's work
- have a look at an existing PR, look at all tabs, show suggestion feature
- but sometimes we want to really build and try sth out ...
- `git remote -v`
- `git remote add alex git@github.com:ajaust/precice.git` if I don't have remote already (or somebody else)
- `git fetch alex`
- `git checkout -t alex/[branch-name]`
- I could now also push to `ajaust`'s remote
---
## Useful Links
- [Official documentation](http://git-scm.com/doc)
- [Video: Git in 15 minutes: basics, branching, no remote](https://www.youtube.com/watch?v=USjZcfj8yxE)
- [The GitHub Blog: Commits are snapshots, not diffs](https://github.blog/2020-12-17-commits-are-snapshots-not-diffs/)
- Chapters [6](https://merely-useful.tech/py-rse/git-cmdline.html) and [7](https://merely-useful.tech/py-rse/git-advanced.html) of Research Software Engineering with Python
- [Podcast All Things Git: History of VC](https://www.allthingsgit.com/episodes/the_history_of_vc_with_eric_sink.html)
- [git purr](https://girliemac.com/blog/2017/12/26/git-purr/)
---
# 3. Merge vs. Rebase
---
## Linear History
<img src="https://raw.githubusercontent.com/s-ccs/summerschool_simtech_2023/main/material/2_tue/git/figs/history_linear/fig.png" width=60%; style="margin-left:auto; margin-right:auto; padding-top: 25px; padding-bottom: 25px">
- Commits are snapshots + pointer to parent, not diffs
- But for linear history, this makes no difference
- Each normal commit has one parent commit
- `c05f017^` <-- `c05f017`
- `A` = `B^` <-- `B`
- (`^` is the same as `~1`)
- Pointer to parent commit goes into hash
- `git show` gives diff of commit to parent
---
## Merge Commits
- `git checkout main && git merge feature`
<img src="https://raw.githubusercontent.com/s-ccs/summerschool_simtech_2023/main/material/2_tue/git/figs/history_merge/fig.png" width=70%; style="margin-left:auto; margin-right:auto; padding-top: 25px; padding-bottom: 25px" >
- A merge commit (normally) has two parent commits `M^1` and `M^2` (don't confuse `^2` with `~2`)
- Can't show unique diff
- First parent relative to the branch you are on (`M^1` = `C`, `M^2` = `E`)
- `git show`
- `git show`: *"combined diff"*
- GitHub: `git show --first-parent`
- `git show -m`: separate diff to all parents
---
## Why is a Linear History Important?
We use here:
> Linear history := no merge commits
- Merge commits are hard to understand per se.
- A merge takes all commits from `feature` to `main` (on `git log`). --> Hard to understand
- Developers often follow projects by reading commits (reading the diffs). --> Harder to read (where happened what)
- Tracing bugs easier with linear history (see `git bisect`)
- Example: We know a bug was introduced between `v1.3` and `v1.4`.
---
## How to get a Linear History?
- Real conflicts are very rare in real projects, most merge commits are false positives (not conflicts) and should be avoided.
- If there are no changes on `main`, `git merge` does a *"fast-forward"* merge (no merge commit).
- If there are changes on `main`, rebase `feature` branch.
---
## Rebase
- `git checkout feature && git rebase main`
<img src="https://raw.githubusercontent.com/s-ccs/summerschool_simtech_2023/main/material/2_tue/git/figs/history_rebase/fig.png" width=90%; style="margin-left:auto; margin-right:auto; padding-top: 25px; padding-bottom: 25px">
- States of issues change (and new parents) --> history is rewritten
- If `feature` is already on remote, it needs a force push `git push --force myfork feature` (or `--force-with-lease`).
- Be careful: Only use rebase if **only you** work on a branch (a local branch or a branch on your fork).
- For local branches very helpful: `git pull --rebase` (fetch & rebase)
---
## GitHub PR Merge Variants
- GitHub offers three ways to merge a non-conflicting (no changes in same files) PR:
- Create a merge commit
- Squash and merge
- Rebase and merge
- Look at a PR together, e.g. [PR 1432 from preCICE](https://github.com/precice/precice/pull/1824) (will be closed eventually)
> What do the options do?
---
## Squash and Merge
- ... squashes all commits into one
- Often, single commits of feature branch are important while developing the feature,
- ... but not when the feature is merged
- Works well for small feature PRs
- ... also does a rebase (interactively, `git rebase -i`)
---
## Conflicts
> But what if there is a conflict?
- Resolve by rebasing `feature` branch (recommended)
- Or resolve by merging `main` into `feature`
---
## Summary and Remarks
- Try to keep a linear history with rebasing whenever reasonable
- Don't use rebase on a public/shared branch during development
- Squash before merging if reasonable
- Delete `feature` branch after merging
- Local view: `git log --graph`
- Remote view on GitHub, e.g. [for preCICE](https://github.com/precice/precice/network)
---
## Further Reading
- [Bitbucket docs: "Merging vs. Rebasing"](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)
- [Hackernoon: "What's the diff?"](https://hackernoon.com/git-merge-vs-rebase-whats-the-diff-76413c117333)
- [GitHub Blog: "Commits are snapshots, not diffs"](https://github.blog/2020-12-17-commits-are-snapshots-not-diffs/)
- [Stack Overflow: "Git show of a merge commit"](https://stackoverflow.com/questions/40986518/git-show-of-a-merge-commit?)
---
# 4. Working in Teams / Git Workflows
---
## Why Workflows?
- Git offers a lot of flexibility in managing changes.
- When working in a team, some agreements need to be made however (especially on how to work with branches).
---
## Which Workflow?
- There are standard solutions.
- It depends on the size of the team.
- Workflow should enhance effectiveness of team, not be a burden that limits productivity.
---
## Centralized Workflow
- Only one branch: the `main` branch
- Keep your changes in local commits till some feature is ready
- If ready, directly push to `main`; no PRs, no reviews
- Conflicts: fix locally (push not allowed anyway), use `git pull --rebase`
- **Good for**: small teams, small projects, projects that are anyway reviewed over and over again
- Example: LaTeX papers
- Put each section in separate file
- Put each sentence in separate line
---
## Feature Branch Workflow
- Each feature (or bugfix) in separate branch
- Push feature branch to remote, use descriptive name
- e.g. issue number in name if each branch closes one issue
- `main` should never contain broken code
- Protect direct push to `main`
- PR (or MR) with review to merge from feature branch to `main`
- Rebase feature branch on `main` if necessary
- Delete remote branch once merged and no longer needed (one click on GitHub after merge)
- **Good for**: small teams, small projects, prototyping, websites (continuous deployment), documentation
- Aka. [trunk-based development](https://www.atlassian.com/continuous-delivery/continuous-integration/trunk-based-development) or [GitHub flow](https://guides.github.com/introduction/flow/)
---
## Gitflow
- [Visualization by Vincent Driessen](https://nvie.com/img/git-model@2x.png), from [original blog post in 2010](https://nvie.com/posts/a-successful-git-branching-model/)
- `main` and `develop`
- `main` contains releases as tags
- `develop` contains latest features
- Feature branches created of `develop`, PRs back to `develop`
- Protect `main` and (possibly) `develop` from direct pushes
- Dedicated release branches (e.g., `v1.0`) created of `develop`
- Tested, fixed, merged to `main`
- Afterwards, tagged, merged back to `develop`
- Hotfix branches directly of and to `main`
- **Good for**: software with users, larger teams
- There is a tool `git-flow`, a wrapper around `git`, e.g. `git flow init` ... but not really necessary IMHO
---
## Forking Workflow
- Gitflow + feature branches on other forks
- More control over access rights, distinguish between maintainers and external contributors
- Should maintainers also use branches on their forks?
- Makes overview of branches easier
- Distinguishes between prototype branches (on fork, no PR), serious enhancements (on fork with PR), joint enhancements (on upstream)
- **Good for**: open-source projects with external contributions (used more or less in preCICE)
---
## Do Small PRs
- For all workflows, it is better to do small PRs
- Easier to review
- Faster to merge --> fewer conflicts
- Easier to squash
---
## Quick Reads
- [Atlassian docs on workflows](https://www.atlassian.com/git/tutorials/comparing-workflows)
- [Original gitflow blog post](https://nvie.com/posts/a-successful-git-branching-model/)
- [Trunk-based development](https://www.atlassian.com/continuous-delivery/continuous-integration/trunk-based-development)
- [GitHub flow](https://guides.github.com/introduction/flow/)
- [How to keep pull requests manageable](https://gist.github.com/sktse/569cb192ce1518f83db58567591e3205)
---
# 5. GitHub / GitLab Standards
---
## What Do We Mean With Standards?
- GitHub uses standards or conventions.
- Certain files or names trigger certain behavior automatically.
- Many are supported by most forges.
- **This is good.**
- Everybody should know them.
---
## Special Files
Certain files lead to special formatting (normally directly at root of repo):
- `README.md`
- ... contains meta information / overview / first steps of software.
- ... gets rendered on landing page (and in every folder).
- `LICENSE`
- ... contains software license.
- ... gets rendered on right sidebar, when clicking on license, and on repo preview.
- `CONTRIBUTING.md`
- ... contains guidelines for contributing.
- First-time contributors see banner.
- `CODE_OF_CONDUCT.md`
- ... contains code of conduct.
- ... gets rendered on right sidebar.
---
## Issues and PRs
- Templates for description in `.github` folder
- `closes #34` (or several other keywords: `fixes`, `resolves`) in commit message or PR description will close issue 34 when merged.
- `help wanted` label gets rendered on repo preview (e.g. *"3 issues need help"*).
---
# 6. Commit Messages
---
## Commit Messages (1/2)
- Consistent
- Descriptive and concise (such that complete history becomes skimmable)
- Explain the "why" (the "how" is covered in the diff)
---
## Commit Messages (2/2)
[The seven rules of a great Git commit message](https://chris.beams.io/git-commit/):
- Separate subject from body with a blank line.
- Limit the subject line to 50 characters.
- Capitalize the subject line.
- Do not end the subject line with a period.
- Use the imperative mood in the subject line.
- Wrap the body at 72 characters.
- Use the body to explain what and why vs. how.

View File

@ -1,72 +0,0 @@
---
type: slide
slideOptions:
transition: slide
width: 1400
height: 900
margin: 0.1
---
<style>
.reveal strong {
font-weight: bold;
color: orange;
}
.reveal p {
text-align: left;
}
.reveal section h1 {
color: orange;
}
.reveal section h2 {
color: orange;
}
.reveal code {
font-family: 'Ubuntu Mono';
color: orange;
}
.reveal section img {
background:none;
border:none;
box-shadow:none;
}
</style>
# GitHub / GitLab Standards
---
## What do we mean with Standards?
- GitHub uses standards or conventions.
- Certain files or names trigger certain behavior automatically.
- Many are supported by most forges.
- **This is good.**
- Everybody should know them.
---
## Special Files
Certain files lead to special formatting (normally directly at root of repo):
- `README.md`
- ... contains meta information / overview / first steps of software.
- ... gets rendered on landing page (and in every folder).
- `LICENSE`
- ... contains software license.
- ... gets rendered on right sidebar, when clicking on license, and on repo preview.
- `CONTRIBUTING.md`
- ... contains guidelines for contributing.
- First-time contributors see banner.
- `CODE_OF_CONDUCT.md`
- ... contains code of conduct.
- ... gets rendered on right sidebar.
---
## Issues and PRs
- Templates for description in `.github` folder
- `closes #34` (or several other keywords: `fixes`, `resolves`) in commit message or PR description will close issue 34 when merged.
- `help wanted` label gets rendered on repo preview (e.g. *"3 issues need help"*).

View File

@ -0,0 +1,8 @@
# Tasks
1. Work with any forge that you like and create a user account (we strongly recommend GitHub since we will need it later again).
2. Push your package `MyStatsPackage` to a remote repository.
3. Add a function `printOwner` to the package through a pull request. The function should print your (GitHub) user name (hard-coded).
4. Use the package from somebody else in the classroom and verify with `printOwner` that you use the correct package.
5. Fork this other package and contribute a function `printContributor` to it via a PR. Get a review and get it merged.
6. Add more functions to other packages of classmates that print funny things, but always ensure a linear history.

View File

@ -1,120 +0,0 @@
---
type: slide
slideOptions:
transition: slide
width: 1400
height: 900
margin: 0.1
---
<style>
.reveal strong {
font-weight: bold;
color: orange;
}
.reveal p {
text-align: left;
}
.reveal section h1 {
color: orange;
}
.reveal section h2 {
color: orange;
}
.reveal code {
font-family: 'Ubuntu Mono';
color: orange;
}
</style>
# Working in Teams / Git Workflows
---
## Why Workflows?
- Git offers a lot of flexibility in managing changes.
- When working in a team, some agreements need to be made however (especially on how to work with branches).
---
## Which Workflow?
- There are standard solutions.
- It depends on the size of the team.
- Workflow should enhance effectiveness of team, not be a burden that limits productivity.
---
## Centralized Workflow
- Only one branch: the `main` branch
- Keep your changes in local commits till some feature is ready
- If ready, directly push to `main`; no PRs, no reviews
- Conflicts: fix locally (push not allowed anyway), use `git pull --rebase`
- **Good for**: small teams, small projects, projects that are anyway reviewed over and over again
- Example: LaTeX papers
- Put each section in separate file
- Put each sentence in separate line
---
## Feature Branch Workflow
- Each feature (or bugfix) in separate branch
- Push feature branch to remote, use descriptive name
- e.g. issue number in name if each branch closes one issue
- `main` should never contain broken code
- Protect direct push to `main`
- PR (or MR) with review to merge from feature branch to `main`
- Rebase feature branch on `main` if necessary
- Delete remote branch once merged and no longer needed (one click on GitHub after merge)
- **Good for**: small teams, small projects, prototyping, websites (continuous deployment), documentation
- Aka. [trunk-based development](https://www.atlassian.com/continuous-delivery/continuous-integration/trunk-based-development) or [GitHub flow](https://guides.github.com/introduction/flow/)
---
## Gitflow
- [Visualization by Vincent Driessen](https://nvie.com/img/git-model@2x.png), from [original blog post in 2010](https://nvie.com/posts/a-successful-git-branching-model/)
- `main` and `develop`
- `main` contains releases as tags
- `develop` contains latest features
- Feature branches created of `develop`, PRs back to `develop`
- Protect `main` and (possibly) `develop` from direct pushes
- Dedicated release branches (e.g., `v1.0`) created of `develop`
- Tested, fixed, merged to `main`
- Afterwards, tagged, merged back to `develop`
- Hotfix branches directly of and to `main`
- **Good for**: software with users, larger teams
- There is a tool `git-flow`, a wrapper around `git`, e.g. `git flow init` ... but not really necessary IMHO
---
## Forking Workflow
- Gitflow + feature branches on other forks
- More control over access rights, distinguish between maintainers and external contributors
- Should maintainers also use branches on their forks?
- Makes overview of branches easier
- Distinguishes between prototype branches (on fork, no PR), serious enhancements (on fork with PR), joint enhancements (on upstream)
- **Good for**: open-source projects with external contributions (used more or less in preCICE)
---
## Do Small PRs
- For all workflows, it is better to do small PRs
- Easier to review
- Faster to merge --> fewer conflicts
- Easier to squash
---
## Quick reads
- [Atlassian docs on workflows](https://www.atlassian.com/git/tutorials/comparing-workflows)
- [Original gitflow blog post](https://nvie.com/posts/a-successful-git-branching-model/)
- [Trunk-based development](https://www.atlassian.com/continuous-delivery/continuous-integration/trunk-based-development)
- [GitHub flow](https://guides.github.com/introduction/flow/)
- [How to keep pull requests manageable](https://gist.github.com/sktse/569cb192ce1518f83db58567591e3205)

View File

@ -1,7 +1,12 @@
::: callout
[Link to Slides](slides.qmd)
:::
## Task 1
Solve [task 1](tasks.qmd#1)
----
# Documenter.jl
### File-structure overview
@ -76,6 +81,13 @@ Using `Literate.jl` one does not need to write `.md` files - but rather can use
## this is a comment
```
## Task 2
Solve [task 2](tasks.qmd#2)
----
# PkgTemplate.jl
```julia
]activate --temp
@ -104,4 +116,9 @@ You can also run the PkgTemplate interactively using
Template(interactive=true)("MyPkg")
```
Which will ask you a hundred million questions ;-)
:::
:::
## Task 3
Solve [task 3](tasks.qmd#3)

View File

@ -0,0 +1,84 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Task 1: Docstrings {#1}\n",
"1. Add Docstrings to some of your functions.\n",
"2. Load the package, and check you can see the docstrings using e.g. `?rse_mean`\n",
"\n",
"-----\n",
"\n",
"# Task 2: Documenter.jl {#1}\n",
"### Folderstructure\n",
"1. create folders/files:\n",
"```\n",
"docs/\n",
"├── src/\n",
"├── src/mydocs.jl\n",
"└── make.jl\n",
"```\n",
"\n",
"### add some docs\n",
"2. with mydocs containing\n",
"\n",
"\n",
"````{verbatim}\n",
"```@docs \n",
"func(x)\n",
"```\n",
"\n",
"````\n",
"\n",
"and\n",
"\n",
"`make.jl` containing\n",
"```julia\n",
"using Documenter, Example\n",
"\n",
"makedocs(sitename=\"My Documentation\")\n",
"```\n",
"\n",
"### 3. Generate\n",
"Generate the docs using `include(\"make.jl\")` after activating the `./docs/Project.toml`\n",
"\n",
":::callout\n",
"## Bonus-Task\n",
" Use [`LiveServer.jl`](https://github.com/tlienart/LiveServer.jl) to automatically update a local preview of your documentation (follow [this tutorial](https://github.com/tlienart/LiveServer.jl#serve-docs) )\n",
":::\n",
"\n",
"### 4. Add a tutorial\n",
"Now add a tutorial `./docs/src/tutorial.md` which should contain a brief example simulating some data (using `rand`) and calculating mean, tstat and std on them.\n",
"\n",
"Use the `makedocs(...page=)` keywordargument.\n",
"\n",
"----\n",
"\n",
"# Task 3: PkgTemplate.jl {#3}\n",
"Generate a package MySecondStatsPackage using PkgTemplate. \n",
"\n",
"- Add github-actions for:\n",
" - coverage\n",
" - unittests\n",
" - docs\n",
"- MIT license\n",
"- README.md\n",
"\n",
"::: callout-tipp\n",
" Don't forget to activate the github-page in the github settings!\n",
":::"
],
"id": "7ec915e0"
}
],
"metadata": {
"kernelspec": {
"name": "python3",
"language": "python",
"display_name": "Python 3 (ipykernel)"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,62 @@
# Task 1: Docstrings {#1}
1. Add Docstrings to some of your functions.
2. Load the package, and check you can see the docstrings using e.g. `?rse_mean`
-----
# Task 2: Documenter.jl {#1}
### Folderstructure
1. create folders/files:
```
docs/
├── src/
├── src/mydocs.jl
└── make.jl
```
### add some docs
2. with mydocs containing
````{verbatim}
```@docs
func(x)
```
````
and
`make.jl` containing
```julia
using Documenter, Example
makedocs(sitename="My Documentation")
```
### 3. Generate
Generate the docs using `include("make.jl")` after activating the `./docs/Project.toml`
:::callout
## Bonus-Task
Use [`LiveServer.jl`](https://github.com/tlienart/LiveServer.jl) to automatically update a local preview of your documentation (follow [this tutorial](https://github.com/tlienart/LiveServer.jl#serve-docs) )
:::
### 4. Add a tutorial
Now add a tutorial `./docs/src/tutorial.md` which should contain a brief example simulating some data (using `rand`) and calculating mean, tstat and std on them.
Use the `makedocs(...page=)` keywordargument.
----
# Task 3: PkgTemplate.jl {#3}
Generate a package MySecondStatsPackage using PkgTemplate.
- Add github-actions for:
- coverage
- unittests
- docs
- MIT license
- README.md
::: callout-tipp
Don't forget to activate the github-page in the github settings!
:::

View File

@ -1,7 +1,11 @@
---
---
## Slides
The slides are available [in pptx format here](Julia_Matrices_Optimization_JuMP_Stuttgart2023.pptx). Note that there are a few extra slides in case you are motivated to learn more!
## Exercise
The exercise is available [as a jupyter-notebook here](Julia_Matrices_Optimization_JuMP_Stuttgart2023.ipynb).
The exercise is rendered [as html here](Julia_Matrices_Optimization_JuMP_Stuttgart2023.ipynb) but can also be downloaded {{< downloadthis Julia_Matrices_Optimization_JuMP_Stuttgart2023.ipynb label="Download as ipynb" >}}

View File

@ -229,7 +229,17 @@ data(penguins) * mapping(:bill_length_mm, :bill_depth_mm, color=:species) * (lin
data(penguins) * mapping(:bill_length_mm, :bill_depth_mm, color=:species) * (smooth() + visual(Scatter)) |> draw
```
### Advanced
```julia
h = data(penguins) * mapping(:bill_length_mm, :bill_depth_mm, color=:species) * (smooth() + visual(Scatter)) |> draw
h.grid
ax = h.grid[1,1].axis
ax + tab -> ax.xticks
h
```
## Task 3
[Click here for the next task](tasks.qmd#3)
[Click here for the next task](tasks.qmd#3)

View File

@ -158,4 +158,40 @@ PlutoExtras.BondTable([
```
:::
# Task 3: AlgebraOfGraphics
# Task 3: AlgebraOfGraphics
For this task we need a dataset, and I choose the US EGG dataset for it's simplicity for you.
to load the data, use the following code
```julia
using DataFrames, HTTP, CSV
# dataset via https://github.com/rfordatascience/tidytuesday/tree/master
df = CSV.read(download("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2023/2023-04-11/egg-production.csv"),DataFrame)
```
:::callout-tip
## If you dislike Pluto.jl
If you dont like to use Pluto.jl, you can of course switch back to VSCode. Then you have to create a new environment and add the packages you use before.
:::
## 🥚 vs. 🗓
Visualize the number of eggs against the year
:::callout-tip
To get a first overview, `first(df)` , `describe(df)` and `names(df)` are typically helpful
:::
## Split them up
Next split them up, choose `color` and `col` and choose reasonable columns from the dataset
## Rotate the labels
Use the trick from the handout to modify a plot after it was generated: Rotate the x-label ticks by some 30°
:::callout-tip
instead of rotating each axis manually, you can also replace the `draw` command in your pipeline with an anonymous function. This allows you to specify additional arguments e.g. to the axis, for all "sub"-plots
```julia
... |> x-> draw(x;axis=(;xlims = (-3,2))) # <1>
```
1. Note the `;` before xlims, this enforces that a `NamedTuple` is created

View File

@ -4,4 +4,5 @@ The slides are available [in pptx format here](Julia_Parallel_Distributed_2023_S
## Exercise
The exercise is available [as a jupyter-notebook here](Julia_Parallel_Distributed_2023_Stuttgart.ipynb).
The exercise is rendered [as html here](Julia_Parallel_Distributed_2023_Stuttgart.ipynb) but can also be downloaded {{< downloadthis Julia_Parallel_Distributed_2023_Stuttgart.ipynb label="Download as ipynb" >}}