diff --git a/.gitignore b/.gitignore index 0c6439c5..64ff4eff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,13 @@ .DS_Store* .vscode* +/__pycache__/* .env /venv* -/site -/__pycache__ +/site/* +# pages that are copied in from main repo +/docs/CONTRIBUTING.md +/docs/CODE_OF_CONDUCT.md +/docs/README.md +# pages that are generated from templates +/docs/tables.md +/docs/architecture.md diff --git a/.markdownlint.yaml b/.markdownlint.yaml index 71f3b6e9..90f5fe5c 100644 --- a/.markdownlint.yaml +++ b/.markdownlint.yaml @@ -11,7 +11,10 @@ MD041: false # Remove line length limit MD013: false -# Remove code block style because it also fails on admonition +# Remove "fenced code blocks should have language specified" +MD040: false + +# Remove "no inline HTML" MD046: false # Remove no in line HTML diff --git a/README.md b/README.md index 62de1b4b..ef3934a7 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,43 @@ This repository provides data schemas and tools to support the access, managemen ## TIDES specification -The TIDES specification is maintained in the `/spec` sub-directory as a series of JSON tables compatible with the [frictionless data](https://specs.frictionlessdata.io/table-schema/) table schema standards. +The TIDES specification is maintained in the `/spec` sub-directory as a series of JSON tables compatible with the [frictionless data](https://specs.frictionlessdata.io/table-schema/) table schema and [data package](https://specs.frictionlessdata.io/data-package) standards. Human-friendlier documentation is auto-generated and available at: - [Architecture](https://tides-transit.github.io/TIDES/main/architecture) - [Table Schemas](https://tides-transit.github.io/TIDES/main/tables) +## Example Data + +Sample data can be found in the `/samples` directory, with one directory for each example. + +## Validating TIDES data + +TIDES data with a valid [`datapackage.json`](#data-package) can be easily validated using the [frictionless framework](https://framework.frictionlessdata.io/), which can be installed and invoked as follows: + +```bash +pip install frictionless +frictionless validate path/to/your/datapackage.json +``` + +### Data Package + +To validate a package of TIDES data, you must add a frictionless-compliant [`datapackage.json`](https://specs.frictionlessdata.io/data-package/) alongside your data which describes which files should be validated to which schemas. Most of this can be copied from [`/data/template/datapackage.json`](https://raw.githubusercontent.com/TIDES-transit/TIDES/main/data/template/datapackage.json). + +Once this is created, mapping the data files to the schema, simply run: + +```sh +frictionless validate datapackage.json +``` + +### Specific files + +Specific files can be validated by running the frictionless framework against them and their corresponding schemas as follows: + +```sh +frictionless validate vehicles.csv --schema https://raw.githubusercontent.com/TIDES-transit/TIDES/main/spec/vehicles.schema.json --schema-sync +``` + ## Contributing to TIDES Those who want to help with the development of the TIDES specification should review the guidance in [CONTRIBUTING.md](CONTRIBUTING.md). diff --git a/docs/index.md b/docs/index.md index e31d914c..2578b68e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1 +1,3 @@ -{{ include_file('README.md', downshift_h1= False) }} +# TIDES Transit Specification Suite + +{{ include_file('README.md', start_line = 2, downshift_h1= False) }} diff --git a/docs/samples.md b/docs/samples.md new file mode 100644 index 00000000..7b4125ca --- /dev/null +++ b/docs/samples.md @@ -0,0 +1,9 @@ +# Sample Data + +Sample data can be found in the `/samples` directory, with one directory for each data sample. + +{{ include_file('samples/README.md')}} + +## Data List + +{{ list_samples('samples') }} diff --git a/main.py b/main.py index 820c0711..095780ab 100644 --- a/main.py +++ b/main.py @@ -26,6 +26,30 @@ def define_env(env): - macro: a decorator function, to declare a macro. """ + @env.macro + def list_samples(data_dir: str) -> str: + """Outputs a simple list of the directories in a folder in markdown. + Args: + data_dir (str):directory to search in + Returns: + str: markdown-formatted list + """ + + fields = ["Sample", "Agency", "Resources", "Vendors"] + + data_dir = os.path.join(env.project_dir, data_dir) + samples = [ + d for d in os.listdir(data_dir) if os.path.isdir(os.path.join(data_dir, d)) + ] + + md_table = ( + "| *" + "** | **".join(fields) + "* |\n| " + " ----- |" * len(fields) + "\n" + ) + + for s in samples: + md_table += datapackage_to_row(os.path.join(data_dir, s), fields) + return md_table + @env.macro def include_file( filename: str, downshift_h1=True, start_line: int = 0, end_line: int = None @@ -57,9 +81,8 @@ def include_file( 4: re.compile(r"(#{4}\s)(.*)"), 5: re.compile(r"(#{5}\s)(.*)"), } - print(f"???before downshifting! {full_filename}") + if md_heading_re[1].search(content) and downshift_h1: - print("!!!downshifting!") content = re.sub(md_heading_re[5], r"#\1\2", content) content = re.sub(md_heading_re[4], r"#\1\2", content) content = re.sub(md_heading_re[3], r"#\1\2", content) @@ -137,6 +160,51 @@ def frictionless_schemas( TABLE_TYPES = ["Event", "Summary", "Supporting"] +def datapackage_to_row(dir: str, fields: list) -> str: + """Reads datapackage and translates key metadata to a row in a markdown table. + + Right now, only works for fields: "Sample", "Agency", "Resources", "Vendors" + + Args: + dir (str): fully qualified directory for sample data + fields (list): list of fields to return + + Returns: + str: row in a markdown table with name, agency, resources, vendors + """ + dp_filename = os.path.join(dir, "datapackage.json") + if not os.path.isfile(dp_filename): + raise ValueError(f"Can't find datapackage file:\n {dp_filename}.") + with open(dp_filename, "r") as dp_file: + dp = json.loads(dp_file.read()) + + _vendors = [ + s.get("vendor", None) for r in dp["resources"] for s in r.get("sources", []) + ] + _vendors += dp.get("sources",{}).get("vendor",[]) + + _vendors = list(set(_vendors) - set([None])) + + _md_cells = { + "Sample": _to_sample_readme_link(dp["name"], dir), + "Agency": dp["agency"], + "Resources": ( + "