DataDeps.jl
repository·master·Indexed 41 days ago
https://github.com/oxinabox/datadeps.jlA Julia package for repeatable data setup, providing a mechanism to manage and fetch data dependencies reliably for reproducible research and science. It allows developers to register static data via a declarative block and access it using the `datadep"Name"` macro, handling automatic downloading and path resolution.
What's inside DataDeps.jl
- DataDeps.jl is a package designed for repeatable data setup in Julia, facilitating reproducible data science by managing the downloading and fetching of data dependencies. It provides a standardized way to ensure that the data required by a project is fetched and available in a consistent manner.
Register a data dependency as a ManualDataDep
masterIf you have a data dependency that is directly included within a git repository (rather than being hosted at an external URL), you can register it using theManualDataDepabstraction. This allowsDataDeps.jlto manage and provide access to the data locally within the repository structure.Use recursive structures in DataDep registration
masterThe
fetch_method,post_fetch_method, andhashfields can match the structure ofremote_path. Ifremote_pathis a vector, these fields can be a single value applied to all elements, or a vector of the same length applied element-wise.This allows for granular control, such as providing different checksums per file or applying different extraction methods to different files in a list.
# Example: Different post-fetch methods for different files register(DataDep("eg", "eg message", ["http://example.com/text.txt", "http://example.com/sub1.zip", "http://example.com/sub2.zip"] post_fetch_method = [identity, file->run(`unzip $file`), file->run(`unzip $file`)] )) # Example: Nested recursive structure register(DataDep("eg", "eg message", ["http://example.com/text.txt", ["http://example.com/sub1.zip", "http://example.com/sub2.zip"]] post_fetch_method = [identity, file->run(`unzip $file`)] ))Understand the DataDeps.jl Load Path
masterThe Load Path is the ordered list of directories DataDeps.jl searches to resolve a data dependency. If the data is not found in any of these paths, DataDeps.jl will attempt to download it.
The Load Path is composed of three sources:
- Package load path: Determined by the specific package where the
datadep"NAME"was invoked. - User defined load path: Determined by the
DATADEPS_LOAD_PATHenvironment variable (a colon-separated list). - Standard load path: System-specific locations (e.g., home directory, shared system folders). This can be disabled by setting
DATADEPS_NO_STANDARD_LOAD_PATH=true.
Behavioral differences:
- Loading data: Searches the paths in order for a readable folder.
- Saving data: Searches the paths in order (skipping the package load path) for a writable directory.
You can move data between any folders in the load path without needing to redownload it.
- Package load path: Determined by the specific package where the
How to handle dynamic data with DataDeps.jl
masterDataDeps.jl is designed for static data and does not provide built-in versioning for the data itself. If your data changes, DataDeps.jl cannot force users to download new copies automatically.
If you need to manage dynamic data, consider these workarounds:
- Manual Refresh: Use a
deps/build.jlscript to runrm(datadep"MyData", recursive=true, force=true)during package updates to force a re-download. - Versioned Names: Treat each version of the data as a unique DataDep with a different name.
- Git Integration: If the data is small and plain-text, store it in your repository's
deps/data/folder and use aManualDataDepto reference it. This avoids the need for manual installation when the package is installed via Git.
- Manual Refresh: Use a
How to handle multiple DataDeps with the same name
masterIf multiple packages use the same
DataDepname, DataDeps.jl may load the wrong one. To prevent this, you can move a package's specific data dependency into its own package directory underdeps/data/.For example, a dependency located at
~/.julia/v0.6/EXAMPLEPKG/deps/data/EXAMPLEDATADEP/will be visible only toEXAMPLEPKGand will not conflict with other packages using the nameEXAMPLEDATADEP.Note on file-level loading: If you use
datadep"Name/subfolder/file.txt"and the file is not in the first folder found with thatName, DataDeps.jl will present a recovery dialog. The easiest fix is to select the option to delete the folder and retry, which forces DataDeps to check the next folder in the load path.Create custom AbstractDataDep types
masterWhile most use cases are covered by
ManualDataDepor standard automaticDataDeptypes, you can extend DataDeps.jl by defining your ownAbstractDataDeptypes. This is useful for complex workflows that require:- Additional Validation: Performing checks after the download is complete and the
post_fetch_methodhas run. - Data Synthesis: Steps that require working with multiple files simultaneously (which exceeds the capabilities of the standard
post_fetch_method). - Hybrid Workflows: Implementing a
SemiManualDataDeppattern where some steps are user-driven and others are automated.
To implement a custom type, you can model it after the existing
ManualDataDepimplementation or encapsulate an existingDataDepas an element within your new type.- Additional Validation: Performing checks after the download is complete and the
Quickstart: Using DataDeps.jl to manage data
masterDataDeps.jl simplifies getting static files from a remote server onto a local machine and providing a consistent way for programs to locate them.
To use data in your project:
- Host your data anywhere that provides an open HTTP/HTTPS link.
- Write a DataDep registration block in your package.
- Access the data using the
datadep"Dataname/file.csv"syntax. DataDeps.jl handles the download and path resolution automatically. - For Continuous Integration (CI) environments, set the
DATADEPS_ALWAYS_ACCEPTenvironment variable to bypass interactive prompts.
datadep"Dataname/file.csv"Install DataDeps lazily
masterTo avoid downloading data unless it is actually needed, ensure the
datadep"Name"macro is only evaluated when required. DataDeps only triggers a download when the macro is evaluated.Common patterns for lazy installation:
- Conditional assignment: Only evaluate the macro if a certain condition (like
training_mode) is met. - Function default arguments: Use the macro as a default value for a function parameter. The macro is only evaluated if the user calls the function without providing that argument.
# Pattern 1: Conditional assignment data_folder = training_mode ? datadep"SecurityFootage" : "/srv/webcam/today" # Pattern 2: Function default arguments function predict(path=datadep"SecurityFootage") # ... end- Conditional assignment: Only evaluate the macro if a certain condition (like
Install DataDeps.jl
masterInstall
DataDeps.jlusing the standard Julia package manager to ensure it is added to yourProject.tomland automatically available to end-users.using Pkg Pkg.add("DataDeps") # Or in the REPL: pkg> add DataDepsMigrate to DataDeps 1.0 fetch API
masterDataDeps 1.0 refactored the download/fetch API to use
Downloads.download()instead ofHTTP.jl. If you are upgrading from a version prior to 1.0, you must update your function calls as several wrappers were removed. The defaultfetch_methodis nowfetch.# Replace removed wrappers with the new fetch API: # 1. Replace fetch_default(remote, dir) fetch(remote, dir) # 2. Replace fetch_base(remote, dir) fetch(remote, dir; update_period=Inf) # 3. Replace fetch_http(remote, dir; update_period=...) fetch(remote, dir; update_period=...) # 4. If overloading download for custom types: # Overload Downloads.download(::YourType) instead of Base.download(::YourType)Install DataDeps eagerly
masterTo ensure data is installed as soon as the package is loaded, place the
datadep"Name"macro inside the package's__init__function (immediately after the registration block).Warning: Do not place the macro at the global scope, as it will run before
__init__and cause an error.If you need to install data at
Pkg.buildtime viadeps/build.jl, you must set the environment variableENV["DATADEPS_ALWAYS_ACCEPT"]="true"because user I/O (like download prompts) is not possible during the build process.function MyPackage.__init__() # Registration code goes here datadep"MyData" # Eagerly trigger download end