diff --git a/.gitignore b/.gitignore index 646f70d..1b0b21e 100644 --- a/.gitignore +++ b/.gitignore @@ -133,4 +133,6 @@ dmypy.json .DS_Store # temp files -tmp/ \ No newline at end of file +tmp/ +Gemfile.lock +_site/* diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..74ed8c6 --- /dev/null +++ b/Gemfile @@ -0,0 +1,31 @@ +source "https://rubygems.org" +# Hello! This is where you manage which Jekyll version is used to run. +# When you want to use a different version, change it below, save the +# file and run `bundle install`. Run Jekyll with `bundle exec`, like so: +# +# bundle exec jekyll serve +# +# This will help ensure the proper Jekyll version is running. +# Happy Jekylling! + +gem "jekyll-theme-minimal" + + +# Following instructions from here: https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/creating-a-github-pages-site-with-jekyll +# gem "jekyll", "~> 4.2.1" +group :jekyll_plugins do + gem "jekyll-remote-theme" + gem "github-pages", "~> 219" +end + +# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem +# and associated library. +platforms :mingw, :x64_mingw, :mswin, :jruby do + gem "tzinfo", "~> 1.2" + gem "tzinfo-data" +end + +# Performance-booster for watching directories on Windows +gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin] + +gem "webrick", "~> 1.7" diff --git a/README.md b/README.md index f549200..737b051 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@ - # Springs +![springs_logo](https://github.com/soldni/springs/raw/main/assets/img/logo.png){:#hero} + A set of utilities to turn [OmegaConf][1] into a fully fledge configuration utils. -Just like the springs inside an Omega watch, they help you move with your experiments. +Just like the springs inside an Omega watch, the Springs library helps you move on with your experiments. Springs overlaps in functionality with [Hydra][2], but without all the unnecessary boilerplate. The current logo for Springs was generated using [DALLĀ·E 2][5]. -To install Springs, simply run +To install Springs from [PyPI][6], simply run: ```bash pip install springs @@ -26,33 +27,33 @@ We start by writing the following structure configuration import springs as sp from dataclasses import dataclass -# this sub-config is for -# data settings -@dataclass +# Data config +# sp.dataclass is an alias for +# dataclasses.dataclass +@sp.dataclass class DataConfig: # sp.MISSING is an alias to # omegaconf.MISSING path: str = sp.MISSING split: str = 'train' -# this sub-config is for -# model settings -@dataclass +# Model config +@sp.dataclass class ModelConfig: name: str = sp.MISSING num_labels: int = 2 -# this sub-config is for -# experiment settings -@dataclass +# Experiment config +@sp.dataclass class ExperimentConfig: batch_size: int = 16 seed: int = 42 -# this is our overall config -@dataclass +# Overall config +# for our program +@sp.dataclass class Config: data: DataConfig = DataConfig() model: ModelConfig = ModelConfig() @@ -117,7 +118,7 @@ python main.py -c config.yaml Easy, right? -### Fine, We Do Support Support Unstructured Configurations +### Fine, We Do Support Support Unstructured Configs! You are not required to used a structured config with Springs. To use our CLI with a bunch of yaml files and/or command line arguments, simply decorate your main function with no arguments. @@ -137,7 +138,7 @@ instantiate an object from it. Springs supports this use case, and it is as easy as providing a `_target_` node in a configuration: ```python -@dataclass +@sp.dataclass class ModelConfig: _target_: str = ( 'transformers.' @@ -154,13 +155,13 @@ In your experiment code, run: ```python def run_model(model_config: ModelConfig): ... - model = sp.init.now(model_config, ModelConfig) + model = sp.init.now( + model_config, ModelConfig + ) ``` -**Note:** Previous versions of Springs supported specifying the return type, -but now it is actively encouraged. Running `sp.init.now(model_config)` will -now raise a warning if the type is not provided. To prevent this warning, -use `sp.toggle_warnings(False)` before calling `sp.init.now`/ `sp.init.later`. +**Note:** While previous versions of Springs merely supported specifying the return type, now it is actively and strongly encouraged. +Running `sp.init.now(model_config)` will raise a warning if the type is not provided. To prevent this warning, use `sp.toggle_warnings(False)` before calling `sp.init.now`/ `sp.init.later`. ### `init.now` vs `init.later` @@ -188,7 +189,7 @@ If, for some reason, cannot specify the path to a class as a string, you can use ```python import transformers -@dataclass +@sp.dataclass class ModelConfig: _target_: str = sp.Target.to_string( transformers. @@ -208,7 +209,9 @@ To enable it, pass the expected return type when initializing an object: ```python @sp.cli(TokenizerConfig) def main(config: TokenizerConfig): - tokenizer = sp.init(config, PreTrainedTokenizerBase) + tokenizer = sp.init( + config, PreTrainedTokenizerBase + ) print(tokenizer) ``` @@ -220,13 +223,12 @@ This will raise an error when the tokenizer is not a subclass of `PreTrainedToke Sometimes a configuration has some default parameters, but others are optional and depend on other factors, such as the `_target_` class. In these cases, it is convenient to set up a flexible dataclass, using `make_flexy` after the `dataclass` decorator. ```python -@sp.make_flexy -@dataclass +@sp.flexyclass class MetricConfig: _target_: str = sp.MISSING average: str = 'macro' -config = sp.from_flexyclass(MetricConfig) +config = sp.from_dataclass(MetricConfig) overrides = { # we override the _target_ '_target_': 'torchmetrics.F1Score', @@ -235,7 +237,8 @@ overrides = { 'num_classes': 2 } -config = sp.merge(config, sp.from_dict(overrides)) +config = sp.merge(config, + sp.from_dict(overrides)) print(config) # this will print the following: # { @@ -245,13 +248,6 @@ print(config) # } ``` -**Note:** In previous version of Springs, the canonical way to create a flexible class was to decorate a class with `@sp.flexyclass`. This method is still there, but it is not encouraged since it creates issues with `mypy` (and potentially other type checkers). Please consider switching to `dataclass` followed by `make_flexy`. To prevent a warning being raised for this, use -`sp.toggle_warnings(False)` before calling `sp.flexyclass`. - -### Resolvers - -Guide coming soon! - ## Tips and Tricks This section includes a bunch of tips and tricks for working with OmegaConf and YAML. @@ -299,3 +295,4 @@ test_config: [3]: https://devblogs.microsoft.com/python/announcing-pylance-fast-feature-rich-language-support-for-python-in-visual-studio-code/ [4]: https://code.visualstudio.com [5]: https://openai.com/dall-e-2/ +[6]: https://pypi.org/project/springs/ diff --git a/_config.yml b/_config.yml index 6bc6111..9e5a873 100644 --- a/_config.yml +++ b/_config.yml @@ -1,6 +1,5 @@ theme: jekyll-theme-minimal - title: Springs -description: A set of utilities to turn Dataclasses into useful configuration managers. -logo: /static/logo.png +description: A set of utilities to create and manage typed configuration files effectively, built on top of OmegaConf. +logo: /assets/img/logo.png google_analytics: G-LXRX72YD7R diff --git a/_includes/head-custom-google-analytics.html b/_includes/head-custom-google-analytics.html new file mode 100644 index 0000000..4b5b3fc --- /dev/null +++ b/_includes/head-custom-google-analytics.html @@ -0,0 +1,9 @@ + + + diff --git a/assets/css/style.scss b/assets/css/style.scss new file mode 100644 index 0000000..92b92f0 --- /dev/null +++ b/assets/css/style.scss @@ -0,0 +1,95 @@ +--- +--- + +@import "{{ site.theme }}"; + +@import url('https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:ital,wght@0,400;0,700;1,400;1,700&display=swap'); + + +header { + font-family: 'Atkinson Hyperlegible', sans-serif; + font-size: 90%; + line-height: 1.3; + p { + text-align: left; + } + + h1 { + font-size: 2.5em; + } + + @media(max-width: 960px) { + text-align: center; + padding: 0; + p {text-align: center} + h1 {text-align: center} + + // float: center; + // margin-top: -8px; + // margin-left: auto; + // margin-right: auto; + } +} + +body { + text-align: justify; + + font-family: 'Atkinson Hyperlegible', sans-serif; + font-size: 100%; + line-height: 1.3; + + // hide title when not on github + h1#springs { + visibility: hidden; + height: 0px; + margin-top: 0; + margin-bottom: -1.5em; + } + img#hero{ + visibility: hidden; + height: 0px; + } + +} + + + +h1, h2, h3, h4, h5, h6 { + text-align: left; +} + +li { + text-align: left; +} + + +/* mouse over link */ +a:hover { + color: #CA3B7D; + font-style: normal; + font-weight: normal; + text-decoration: none; +} + +code { + font-size: .8em; +} + + +h1 { + a:hover { + font-weight: bold; + text-decoration: none; + } +} + +p.view { + margin-top: 5em; + @media(max-width: 960px) { + margin-top: 1em; + } +} + +footer { + visibility: hidden; +} diff --git a/static/logo.png b/assets/img/logo.png similarity index 100% rename from static/logo.png rename to assets/img/logo.png diff --git a/pyproject.toml b/pyproject.toml index 4c14e52..f4a7c0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "springs" -version = "1.4" -description = "A set of utilities to create and manage configuration files effectively, built on top of OmegaConf." +version = "1.4.1" +description = "A set of utilities to create and manage typed configuration files effectively, built on top of OmegaConf." authors = [ {name = "Luca Soldaini", email = "luca@soldaini.net" } ] diff --git a/res/springs.sketch b/res/springs.sketch new file mode 100644 index 0000000..e0210d3 Binary files /dev/null and b/res/springs.sketch differ diff --git a/scripts/preview-website.sh b/scripts/preview-website.sh new file mode 100755 index 0000000..3f0ec07 --- /dev/null +++ b/scripts/preview-website.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# get script directory +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + SCRIPT_DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + SOURCE="$(readlink "$SOURCE")" + # if $SOURCE was a relative symlink, we need to resolve it + # relative to the path where the symlink file was located + [[ $SOURCE != /* ]] && SOURCE="$SCRIPT_DIR/$SOURCE" +done +SCRIPT_DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + +bundle install && bundle exec jekyll serve