From 517c62b29ce01ad7fc60882f39ca7e4a0a80c2c5 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Tue, 2 Apr 2024 19:33:44 -0700 Subject: [PATCH 01/35] initial draft of export xref script (only extracts operator names, namespace, and parameters atm) --- modules/export-xref.ipynb | 195 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 modules/export-xref.ipynb diff --git a/modules/export-xref.ipynb b/modules/export-xref.ipynb new file mode 100644 index 0000000..246ceeb --- /dev/null +++ b/modules/export-xref.ipynb @@ -0,0 +1,195 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# import libraries\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [], + "source": [ + "# function to extract operator names, location, and namespace from a given source folder\n", + "def extract_operator_names_location_namespace(directory):\n", + " file_list = []\n", + " operator_list = []\n", + " namespace_list = []\n", + " property_list = []\n", + " for root, dirs, files in os.walk(directory):\n", + " for file in files:\n", + " if file.endswith(\"cs\"):\n", + " # skips .cs files in debug and release folder that arent Bonsai operators\n", + " # some operators (for instance NumpyHelper and TimeSeriesOxyPlotBase) do not show up in API docs but nsure why\n", + " if \"Release\" not in root:\n", + " if \"Debug\" not in root:\n", + " if \"Properties\" not in root:\n", + " operator_property_list = []\n", + " file_list.append(os.path.join(root, file))\n", + " operator_list.append(file[:-3])\n", + " with open(os.path.join(root, file), 'r') as cs_file:\n", + " # Read the file line by line\n", + " for line in cs_file:\n", + " # Check if the line contains a namespace declaration\n", + " if \"namespace\" in line:\n", + " # Extract the namespace from the line, strips bracket if any\n", + " namespace = line.strip().split(\" \")[1]\n", + " namespace_list.append(namespace)\n", + " # Stop searching after finding the namespace declaration (add it back in if property extraction is not needed)\n", + " # break \n", + " # this \"hackety\" approach relies on finding all public declarations and omitting certain declarations\n", + " # the alternative approach of finding positive declaration fails because some properties are declared with package specific components \n", + " # example of previous approach: elif line.strip().startswith((\"public string\",\"public TypeMapping\", \"public double\", \"public StateComponent\")):\n", + " \n", + " # this method was tested on machine learning docs \n", + " elif line.strip().startswith(\"public\"):\n", + " if \"class\" in line:\n", + " pass\n", + " elif \"()\" in line:\n", + " pass\n", + " elif \"Process\" in line:\n", + " pass\n", + " elif \"override\" in line:\n", + " pass\n", + " elif \"Event\" in line:\n", + " pass\n", + " elif \"static\" in line:\n", + " pass\n", + " elif \"readonly\" in line:\n", + " pass\n", + " elif \"PyObject\" in line:\n", + " pass\n", + " elif \"(string\" in line:\n", + " pass\n", + " elif \"(double\" in line:\n", + " pass\n", + " elif \"void\" in line:\n", + " pass\n", + " else:\n", + " property = line.strip().split(\" \")[2]\n", + " operator_property_list.append(property)\n", + " property_list.append(operator_property_list) \n", + " operator_dictionary = {operator_list[i]: [file_list[i],namespace_list[i],property_list[i]] for i in range(len(file_list))}\n", + " return operator_dictionary" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "# define folder constants\n", + "current_dir = os.getcwd()\n", + "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))+\"\\\\\"\n", + "docs_dir = root_dir + \"docs\"\n", + "src_dir = root_dir +\"src\"" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [], + "source": [ + "# extract operator dictionary containing operator name as a key and a tuple value with location and namespace)\n", + "operator_dictionary = extract_operator_names_location_namespace(src_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ChannelTriggers ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ChannelTriggers.cs', 'Bonsai.PulsePal', ['ChannelTriggers']]\n", + "CombinatorTypeConverter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CombinatorTypeConverter.cs', 'Bonsai.PulsePal', []]\n", + "ConfigureChannelParameter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureChannelParameter.cs', 'Bonsai.PulsePal', ['DeviceName', 'Parameter']]\n", + "ConfigureOutputChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureOutputChannel.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", + "ConfigureTriggerChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureTriggerChannel.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", + "CreatePulsePal ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CreatePulsePal.cs', 'Bonsai.PulsePal', ['DeviceName', 'PortName', 'OutputChannels', 'TriggerChannels']]\n", + "CustomPulseTrain ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomPulseTrain.cs', 'Bonsai.PulsePal', []]\n", + "CustomTrainId ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomTrainId.cs', 'Bonsai.PulsePal', ['CustomTrainId']]\n", + "CustomTrainTarget ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomTrainTarget.cs', 'Bonsai.PulsePal', ['CustomTrainTarget']]\n", + "DeviceNameConverter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\DeviceNameConverter.cs', 'Bonsai.PulsePal', []]\n", + "OutputChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\OutputChannel.cs', 'Bonsai.PulsePal', ['OutputChannel']]\n", + "ParameterCode ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ParameterCode.cs', 'Bonsai.PulsePal', []]\n", + "PolymorphicCombinator ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PolymorphicCombinator.cs', 'Bonsai.PulsePal', ['descr)']]\n", + "PulseOnset ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulseOnset.cs', 'Bonsai.PulsePal', ['Time', 'Voltage']]\n", + "PulsePalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalConfiguration.cs', 'Bonsai.PulsePal', ['PortName']]\n", + "PulsePalDevice ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalDevice.cs', 'Bonsai.PulsePal', ['FirmwareVersion', 'IsOpen', 'pulsePal)']]\n", + "PulsePalDisposable ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalDisposable.cs', 'Bonsai.PulsePal', ['pulsePal,', 'PulsePal', 'IsDisposed']]\n", + "PulsePalManager ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalManager.cs', 'Bonsai.PulsePal', []]\n", + "SendCustomPulseTrain ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SendCustomPulseTrain.cs', 'Bonsai.PulsePal', ['DeviceName', 'CustomTrainIdentity']]\n", + "SendCustomWaveform ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SendCustomWaveform.cs', 'Bonsai.PulsePal', ['DeviceName', 'CustomTrainIdentity', 'SamplingPeriod']]\n", + "SetFixedVoltage ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SetFixedVoltage.cs', 'Bonsai.PulsePal', ['DeviceName', 'Channel', 'Voltage']]\n", + "TriggerChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerChannel.cs', 'Bonsai.PulsePal', ['TriggerChannel']]\n", + "TriggerMode ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerMode.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", + "TriggerOutputChannels ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerOutputChannels.cs', 'Bonsai.PulsePal', ['DeviceName', 'Channels']]\n", + "UpdateDisplay ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\UpdateDisplay.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", + "BiphasicConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\BiphasicConfiguration.cs', 'Bonsai.PulsePal', ['Biphasic']]\n", + "BurstDurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\BurstDurationConfiguration.cs', 'Bonsai.PulsePal', ['BurstDuration']]\n", + "ChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\ChannelParameterConfiguration.cs', 'Bonsai.PulsePal', []]\n", + "ContinuousLoopConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\ContinuousLoopConfiguration.cs', 'Bonsai.PulsePal', ['ContinuousLoop']]\n", + "CustomTrainIdentityConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainIdentityConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainIdentity']]\n", + "CustomTrainLoopConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainLoopConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainLoop']]\n", + "CustomTrainTargetConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainTargetConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainTarget']]\n", + "InterBurstIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterBurstIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterBurstInterval']]\n", + "InterPhaseIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterPhaseIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterPhaseInterval']]\n", + "InterPulseIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterPulseIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterPulseInterval']]\n", + "OutputChannelConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelConfiguration.cs', 'Bonsai.PulsePal', ['Biphasic', 'Phase1Voltage', 'Phase2Voltage', 'RestingVoltage', 'PulseTrainDelay', 'Phase1Duration', 'InterPhaseInterval', 'Phase2Duration', 'InterPulseInterval', 'BurstDuration', 'InterBurstInterval', 'PulseTrainDuration', 'CustomTrainIdentity', 'CustomTrainTarget', 'CustomTrainLoop', 'TriggerOnChannel1', 'TriggerOnChannel2', 'ContinuousLoop']]\n", + "OutputChannelConfigurationCollection ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelConfigurationCollection.cs', 'Bonsai.PulsePal', []]\n", + "OutputChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelParameterConfiguration.cs', 'Bonsai.PulsePal', ['Channel']]\n", + "Phase1DurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase1DurationConfiguration.cs', 'Bonsai.PulsePal', ['Phase1Duration']]\n", + "Phase1VoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase1VoltageConfiguration.cs', 'Bonsai.PulsePal', ['Phase1Voltage']]\n", + "Phase2DurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase2DurationConfiguration.cs', 'Bonsai.PulsePal', ['Phase2Duration']]\n", + "Phase2VoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase2VoltageConfiguration.cs', 'Bonsai.PulsePal', ['Phase2Voltage']]\n", + "PulseTrainDelayConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\PulseTrainDelayConfiguration.cs', 'Bonsai.PulsePal', ['PulseTrainDelay']]\n", + "PulseTrainDurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\PulseTrainDurationConfiguration.cs', 'Bonsai.PulsePal', ['PulseTrainDuration']]\n", + "RestingVoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\RestingVoltageConfiguration.cs', 'Bonsai.PulsePal', ['RestingVoltage']]\n", + "TriggerChannelConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelConfiguration.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", + "TriggerChannelConfigurationCollection ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelConfigurationCollection.cs', 'Bonsai.PulsePal', []]\n", + "TriggerChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelParameterConfiguration.cs', 'Bonsai.PulsePal', ['Channel']]\n", + "TriggerModeConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerModeConfiguration.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", + "TriggerOnChannel1Configuration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerOnChannel1Configuration.cs', 'Bonsai.PulsePal', ['TriggerOnChannel1']]\n", + "TriggerOnChannel2Configuration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerOnChannel2Configuration.cs', 'Bonsai.PulsePal', ['TriggerOnChannel2']]\n" + ] + } + ], + "source": [ + "for key, value in operator_dictionary.items():\n", + " print(key, value)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 5cd752d4e6dc160cb2a499d5f19f1feb11240189 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 22 Apr 2024 03:03:38 -0700 Subject: [PATCH 02/35] added draft of copy-files function --- assets/docs/.gitignore | 1 + modules/Copy-Files.ipynb | 78 +++++++++++++++++++++++++++++++++++++++ modules/export-xref.ipynb | 6 +-- 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 assets/docs/.gitignore create mode 100644 modules/Copy-Files.ipynb diff --git a/assets/docs/.gitignore b/assets/docs/.gitignore new file mode 100644 index 0000000..c08f9ad --- /dev/null +++ b/assets/docs/.gitignore @@ -0,0 +1 @@ +_site \ No newline at end of file diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb new file mode 100644 index 0000000..2b4569f --- /dev/null +++ b/modules/Copy-Files.ipynb @@ -0,0 +1,78 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import shutil" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "# define folder constants\n", + "current_dir = os.getcwd()\n", + "assets_dir = os.path.join(os.path.dirname(current_dir), \"assets\")\n", + "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", + "docs_dir = os.path.join(root_dir,\"docs\")\n", + "src_dir = os.path.join(root_dir, \"src\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c:\\Users\\shawn\\Desktop\\docfx-tools_dev\\modules\n", + "c:\\Users\\shawn\\Desktop\\docfx-tools_dev\\assets\n" + ] + } + ], + "source": [ + "print(current_dir)\n", + "print(assets_dir)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# copy docs .gitignore file \n", + "shutil.copy((os.path.join(assets_dir), \".gitignore\"), docs_dir)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/modules/export-xref.ipynb b/modules/export-xref.ipynb index 246ceeb..e925b94 100644 --- a/modules/export-xref.ipynb +++ b/modules/export-xref.ipynb @@ -87,9 +87,9 @@ "source": [ "# define folder constants\n", "current_dir = os.getcwd()\n", - "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))+\"\\\\\"\n", - "docs_dir = root_dir + \"docs\"\n", - "src_dir = root_dir +\"src\"" + "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", + "docs_dir = os.path.join(root_dir,\"docs\")\n", + "src_dir = os.path.join(root_dir, \"src\")" ] }, { From 92cdb7e6a15cde69b4d8f79e4c3a3693cc8d9b9c Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 22 Apr 2024 03:34:56 -0700 Subject: [PATCH 03/35] updated copy-file function to add .gitignore file to docs/api folder --- assets/docs/api/.gitignore | 2 ++ modules/Copy-Files.ipynb | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 assets/docs/api/.gitignore diff --git a/assets/docs/api/.gitignore b/assets/docs/api/.gitignore new file mode 100644 index 0000000..5bca622 --- /dev/null +++ b/assets/docs/api/.gitignore @@ -0,0 +1,2 @@ +*.yml +.manifest \ No newline at end of file diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index 2b4569f..7cf648f 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -19,8 +19,11 @@ "# define folder constants\n", "current_dir = os.getcwd()\n", "assets_dir = os.path.join(os.path.dirname(current_dir), \"assets\")\n", + "assets_docs_dir = os.path.join(assets_dir, \"docs\")\n", + "assets_docs_api_dir = os.path.join(assets_docs_dir, \"api\")\n", "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", "docs_dir = os.path.join(root_dir,\"docs\")\n", + "docs_api_dir = os.path.join(docs_dir, \"api\")\n", "src_dir = os.path.join(root_dir, \"src\")" ] }, @@ -49,8 +52,18 @@ "metadata": {}, "outputs": [], "source": [ - "# copy docs .gitignore file \n", - "shutil.copy((os.path.join(assets_dir), \".gitignore\"), docs_dir)" + "# copy docs .gitignore file to filter out _site folder\n", + "shutil.copy(os.path.join(assets_docs_dir, \".gitignore\"), docs_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# copy docs/api .gitignore file to filter out automatically generated api yml and manifest file\n", + "shutil.copy(os.path.join(assets_docs_api_dir, \".gitignore\"), docs_api_dir)" ] } ], From 4beb3a3b8536ebb8f2c88cf7b3b109ea3af98a93 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 22 Apr 2024 18:09:24 -0700 Subject: [PATCH 04/35] updated copy-file script for .bonsai env --- modules/Copy-Files.ipynb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index 7cf648f..a4f09ba 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -20,6 +20,7 @@ "current_dir = os.getcwd()\n", "assets_dir = os.path.join(os.path.dirname(current_dir), \"assets\")\n", "assets_docs_dir = os.path.join(assets_dir, \"docs\")\n", + "assets_root_dir = os.path.join(assets_dir, \"root\")\n", "assets_docs_api_dir = os.path.join(assets_docs_dir, \"api\")\n", "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", "docs_dir = os.path.join(root_dir,\"docs\")\n", @@ -56,6 +57,16 @@ "shutil.copy(os.path.join(assets_docs_dir, \".gitignore\"), docs_dir)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# copy .bonsai folder for making bonsai env \n", + "shutil.copytree(os.path.join(assets_root_dir, \".bonsai\"), os.path.join(root_dir, \".bonsai\"))" + ] + }, { "cell_type": "code", "execution_count": null, From c6a44dbb6b9fa3d9c1c8720207e1b44194f353e9 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 22 Apr 2024 18:19:15 -0700 Subject: [PATCH 05/35] forgot to add actual .bonsai env --- assets/root/.bonsai/.gitignore | 3 ++ assets/root/.bonsai/Bonsai.config | 49 +++++++++++++++++++++++++++++++ assets/root/.bonsai/NuGet.config | 8 +++++ assets/root/.bonsai/Setup.cmd | 4 +++ assets/root/.bonsai/Setup.ps1 | 21 +++++++++++++ 5 files changed, 85 insertions(+) create mode 100644 assets/root/.bonsai/.gitignore create mode 100644 assets/root/.bonsai/Bonsai.config create mode 100644 assets/root/.bonsai/NuGet.config create mode 100644 assets/root/.bonsai/Setup.cmd create mode 100644 assets/root/.bonsai/Setup.ps1 diff --git a/assets/root/.bonsai/.gitignore b/assets/root/.bonsai/.gitignore new file mode 100644 index 0000000..16e6b2f --- /dev/null +++ b/assets/root/.bonsai/.gitignore @@ -0,0 +1,3 @@ +*.exe +*.exe.* +Packages \ No newline at end of file diff --git a/assets/root/.bonsai/Bonsai.config b/assets/root/.bonsai/Bonsai.config new file mode 100644 index 0000000..e85ebbb --- /dev/null +++ b/assets/root/.bonsai/Bonsai.config @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/root/.bonsai/NuGet.config b/assets/root/.bonsai/NuGet.config new file mode 100644 index 0000000..97e8b73 --- /dev/null +++ b/assets/root/.bonsai/NuGet.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/root/.bonsai/Setup.cmd b/assets/root/.bonsai/Setup.cmd new file mode 100644 index 0000000..92d983d --- /dev/null +++ b/assets/root/.bonsai/Setup.cmd @@ -0,0 +1,4 @@ +@echo off +pushd %~dp0 +powershell -ExecutionPolicy Bypass -File ./Setup.ps1 +popd \ No newline at end of file diff --git a/assets/root/.bonsai/Setup.ps1 b/assets/root/.bonsai/Setup.ps1 new file mode 100644 index 0000000..01cfba6 --- /dev/null +++ b/assets/root/.bonsai/Setup.ps1 @@ -0,0 +1,21 @@ +Push-Location $PSScriptRoot +if (!(Test-Path "./Bonsai.exe")) { + $release = "https://github.com/bonsai-rx/bonsai/releases/latest/download/Bonsai.zip" + $configPath = "./Bonsai.config" + if (Test-Path $configPath) { + [xml]$config = Get-Content $configPath + $bootstrapper = $config.PackageConfiguration.Packages.Package.where{$_.id -eq 'Bonsai'} + if ($bootstrapper) { + $version = $bootstrapper.version + $release = "https://github.com/bonsai-rx/bonsai/releases/download/$version/Bonsai.zip" + } + } + Invoke-WebRequest $release -OutFile "temp.zip" + Move-Item -Path "NuGet.config" "temp.config" -ErrorAction SilentlyContinue + Expand-Archive "temp.zip" -DestinationPath "." -Force + Move-Item -Path "temp.config" "NuGet.config" -Force -ErrorAction SilentlyContinue + Remove-Item -Path "temp.zip" + Remove-Item -Path "Bonsai32.exe" +} +& .\Bonsai.exe --no-editor +Pop-Location \ No newline at end of file From 8389c56d57c0c62fef3e8936216dd86386eaaaeb Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 22 Apr 2024 18:37:13 -0700 Subject: [PATCH 06/35] added .github to copy-files script, added additional comments to indicate source of assets --- assets/docs/api/.gitignore | 1 + assets/root/.github/workflows/build.yml | 28 ++++++++++++++ assets/root/.github/workflows/docs.yml | 51 +++++++++++++++++++++++++ modules/Copy-Files.ipynb | 16 +++++++- 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 assets/root/.github/workflows/build.yml create mode 100644 assets/root/.github/workflows/docs.yml diff --git a/assets/docs/api/.gitignore b/assets/docs/api/.gitignore index 5bca622..adc91e4 100644 --- a/assets/docs/api/.gitignore +++ b/assets/docs/api/.gitignore @@ -1,2 +1,3 @@ +# auto-generated files *.yml .manifest \ No newline at end of file diff --git a/assets/root/.github/workflows/build.yml b/assets/root/.github/workflows/build.yml new file mode 100644 index 0000000..409f5bb --- /dev/null +++ b/assets/root/.github/workflows/build.yml @@ -0,0 +1,28 @@ +name: Build + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + name: Build Solution + runs-on: windows-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v1 + + - name: Setup NuGet + uses: NuGet/setup-nuget@v1.2.0 + + - name: Restore NuGet Packages + run: nuget restore src/Bonsai.Gui.sln + + - name: Build Solution + run: msbuild src/Bonsai.Gui.sln /p:Configuration=Release diff --git a/assets/root/.github/workflows/docs.yml b/assets/root/.github/workflows/docs.yml new file mode 100644 index 0000000..57248ef --- /dev/null +++ b/assets/root/.github/workflows/docs.yml @@ -0,0 +1,51 @@ +# Builds and publishes the documentation website to gh-pages branch +name: Build docs + +on: + workflow_dispatch: + +jobs: + build: + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4.1.1 + with: + submodules: true + + - name: Setup .NET Core SDK + uses: actions/setup-dotnet@v4.0.0 + with: + dotnet-version: 8.x + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + - name: Restore NuGet Packages + run: msbuild -t:restore src\Bonsai.Gui.sln + + - name: Build Solution + run: msbuild src/Bonsai.Gui.sln /p:Configuration=Release + + - name: Setup DocFX + run: dotnet tool restore + + - name: Setup Bonsai + working-directory: .bonsai + run: .\Setup.ps1 + + - name: Build Documentation + working-directory: docs + run: .\build.ps1 + + - name: Checkout gh-pages + uses: actions/checkout@v4.1.1 + with: + ref: gh-pages + path: gh-pages + - name: Publish to github pages + uses: peaceiris/actions-gh-pages@v3.9.3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: docs/_site + force_orphan: true \ No newline at end of file diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index a4f09ba..58a83f9 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -54,6 +54,7 @@ "outputs": [], "source": [ "# copy docs .gitignore file to filter out _site folder\n", + "# asset copied from bonsai-rx/gui\n", "shutil.copy(os.path.join(assets_docs_dir, \".gitignore\"), docs_dir)" ] }, @@ -63,10 +64,22 @@ "metadata": {}, "outputs": [], "source": [ - "# copy .bonsai folder for making bonsai env \n", + "# copy .bonsai folder for making bonsai env\n", + "# asset copied from bonsai-rx/gui \n", "shutil.copytree(os.path.join(assets_root_dir, \".bonsai\"), os.path.join(root_dir, \".bonsai\"))" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# copy .github/workflow for github actions\n", + "# asset copied from bonsai-rx/gui \n", + "shutil.copytree(os.path.join(assets_root_dir, \".github\"), os.path.join(root_dir, \".github\"))" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,6 +87,7 @@ "outputs": [], "source": [ "# copy docs/api .gitignore file to filter out automatically generated api yml and manifest file\n", + "# asset copied from bonsai-rx/gui \n", "shutil.copy(os.path.join(assets_docs_api_dir, \".gitignore\"), docs_api_dir)" ] } From 295398b886f83f471fbeb4b8e18db13166319de3 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 22 Apr 2024 19:13:02 -0700 Subject: [PATCH 07/35] added template folder and build.ps1 to copy files script --- assets/docs/build.ps1 | 2 ++ assets/docs/template/public/main.css | 1 + assets/docs/template/public/main.js | 13 +++++++++++++ modules/Copy-Files.ipynb | 27 ++++++++++++++++++++++++++- 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 assets/docs/build.ps1 create mode 100644 assets/docs/template/public/main.css create mode 100644 assets/docs/template/public/main.js diff --git a/assets/docs/build.ps1 b/assets/docs/build.ps1 new file mode 100644 index 0000000..9d1d453 --- /dev/null +++ b/assets/docs/build.ps1 @@ -0,0 +1,2 @@ +.\bonsai\modules\Export-Image.ps1 "..\src\Bonsai.Gui.ZedGraph\bin\Release\net472" +dotnet docfx @args \ No newline at end of file diff --git a/assets/docs/template/public/main.css b/assets/docs/template/public/main.css new file mode 100644 index 0000000..ee56505 --- /dev/null +++ b/assets/docs/template/public/main.css @@ -0,0 +1 @@ +@import "workflow.css"; \ No newline at end of file diff --git a/assets/docs/template/public/main.js b/assets/docs/template/public/main.js new file mode 100644 index 0000000..fa1294e --- /dev/null +++ b/assets/docs/template/public/main.js @@ -0,0 +1,13 @@ +import WorkflowContainer from "./workflow.js" + +export default { + defaultTheme: 'light', + iconLinks: [{ + icon: 'github', + href: 'https://github.com/bonsai-rx/gui', + title: 'GitHub' + }], + start: () => { + WorkflowContainer.init(); + } +} \ No newline at end of file diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index 58a83f9..1a72145 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -75,8 +75,9 @@ "metadata": {}, "outputs": [], "source": [ - "# copy .github/workflow for github actions\n", + "# copy .github folder for github actions\n", "# asset copied from bonsai-rx/gui \n", + "# to add - prompt for package name to modify github actions scripts\n", "shutil.copytree(os.path.join(assets_root_dir, \".github\"), os.path.join(root_dir, \".github\"))" ] }, @@ -90,6 +91,30 @@ "# asset copied from bonsai-rx/gui \n", "shutil.copy(os.path.join(assets_docs_api_dir, \".gitignore\"), docs_api_dir)" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# copy docs/build.ps1 file to export workflow images\n", + "# asset copied from bonsai-rx/gui \n", + "# to add - prompt for package name to modify script\n", + "shutil.copy(os.path.join(assets_docs_dir, \"build.ps1\"), docs_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# copy docs/template folder\n", + "# asset copied from bonsai-rx/gui \n", + "# to add - prompt for package name to modify github link\n", + "shutil.copytree(os.path.join(assets_docs_dir, \"template\"), os.path.join(docs_dir, \"template\"))" + ] } ], "metadata": { From 685d774b94a320a0aeae3e54db9346f19d8fe4ff Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Tue, 23 Apr 2024 08:07:48 -0700 Subject: [PATCH 08/35] added section to make folders in copy-files --- modules/Copy-Files.ipynb | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index 1a72145..1f97952 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -25,6 +25,8 @@ "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", "docs_dir = os.path.join(root_dir,\"docs\")\n", "docs_api_dir = os.path.join(docs_dir, \"api\")\n", + "docs_workflows_dir = os.path.join(docs_dir, \"workflows\")\n", + "docs_articles_dir = os.path.join(docs_dir, \"articles\")\n", "src_dir = os.path.join(root_dir, \"src\")" ] }, @@ -115,6 +117,36 @@ "# to add - prompt for package name to modify github link\n", "shutil.copytree(os.path.join(assets_docs_dir, \"template\"), os.path.join(docs_dir, \"template\"))" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# make folders for docfx\n", + "# try except blocks in case folder alreaady exists\n", + "try:\n", + " os.mkdir(docs_dir)\n", + "except:\n", + " pass\n", + "\n", + "try:\n", + " os.mkdir(docs_api_dir)\n", + "except:\n", + " pass\n", + "\n", + "try:\n", + " os.mkdir(docs_workflows_dir)\n", + "except:\n", + " pass\n", + "\n", + "try:\n", + " os.mkdir(docs_article_dir)\n", + "except:\n", + " pass\n", + "\n" + ] } ], "metadata": { From 7624da2e45d632deb54eb042e5f77cb724f8deac Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Tue, 23 Apr 2024 08:09:16 -0700 Subject: [PATCH 09/35] corrected spelling mistake in function to make docs_articles_dir --- modules/Copy-Files.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index 1f97952..f89ee7e 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -142,7 +142,7 @@ " pass\n", "\n", "try:\n", - " os.mkdir(docs_article_dir)\n", + " os.mkdir(docs_articles_dir)\n", "except:\n", " pass\n", "\n" From 884c5ce57e3f2952f2a1aea57dac199c5ead47c5 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Tue, 23 Apr 2024 08:40:19 -0700 Subject: [PATCH 10/35] added workflows folder to copy to copy-files --- assets/docs/workflows/.gitignore | 2 + modules/Copy-Files.ipynb | 106 ++++++++++++++++++++----------- 2 files changed, 70 insertions(+), 38 deletions(-) create mode 100644 assets/docs/workflows/.gitignore diff --git a/assets/docs/workflows/.gitignore b/assets/docs/workflows/.gitignore new file mode 100644 index 0000000..af455cb --- /dev/null +++ b/assets/docs/workflows/.gitignore @@ -0,0 +1,2 @@ +*.layout +*.svg \ No newline at end of file diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index f89ee7e..073af1a 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 14, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -22,6 +22,7 @@ "assets_docs_dir = os.path.join(assets_dir, \"docs\")\n", "assets_root_dir = os.path.join(assets_dir, \"root\")\n", "assets_docs_api_dir = os.path.join(assets_docs_dir, \"api\")\n", + "assets_workflows_dir = os.path.join(assets_docs_dir, \"workflows\")\n", "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", "docs_dir = os.path.join(root_dir,\"docs\")\n", "docs_api_dir = os.path.join(docs_dir, \"api\")\n", @@ -32,32 +33,46 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 4, "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "c:\\Users\\shawn\\Desktop\\docfx-tools_dev\\modules\n", - "c:\\Users\\shawn\\Desktop\\docfx-tools_dev\\assets\n" - ] + "data": { + "text/plain": [ + "'c:\\\\Users\\\\shawn\\\\docs'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "print(current_dir)\n", - "print(assets_dir)\n" + "# copy docs .gitignore file to filter out _site folder\n", + "# asset copied from bonsai-rx/gui 4/22/24\n", + "shutil.copy(os.path.join(assets_docs_dir, \".gitignore\"), docs_dir)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "'c:\\\\Users\\\\shawn\\\\.bonsai'" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# copy docs .gitignore file to filter out _site folder\n", - "# asset copied from bonsai-rx/gui\n", - "shutil.copy(os.path.join(assets_docs_dir, \".gitignore\"), docs_dir)" + "# copy .bonsai folder for making bonsai env\n", + "# asset copied from bonsai-rx/gui 4/22/24\n", + "shutil.copytree(os.path.join(assets_root_dir, \".bonsai\"), os.path.join(root_dir, \".bonsai\"))" ] }, { @@ -66,32 +81,55 @@ "metadata": {}, "outputs": [], "source": [ - "# copy .bonsai folder for making bonsai env\n", - "# asset copied from bonsai-rx/gui \n", - "shutil.copytree(os.path.join(assets_root_dir, \".bonsai\"), os.path.join(root_dir, \".bonsai\"))" + "# copy docs/workflows folder\n", + "# asset copied from bonsai-rx/gui 4/23/24\n", + "shutil.copytree(assets_workflows_dir, docs_workflows_dir)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "'c:\\\\Users\\\\shawn\\\\.github'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# copy .github folder for github actions\n", - "# asset copied from bonsai-rx/gui \n", + "# asset copied from bonsai-rx/gui 4/22/24\n", "# to add - prompt for package name to modify github actions scripts\n", "shutil.copytree(os.path.join(assets_root_dir, \".github\"), os.path.join(root_dir, \".github\"))" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "TypeError", + "evalue": "copytree() missing 1 required positional argument: 'dst'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[7], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# copy docs/api folder and .gitignore file to filter out automatically generated api yml and manifest file\u001b[39;00m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;66;03m# asset copied from bonsai-rx/gui 4/22/24\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m shutil\u001b[38;5;241m.\u001b[39mcopytree(os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mjoin(assets_docs_api_dir, docs_api_dir))\n", + "\u001b[1;31mTypeError\u001b[0m: copytree() missing 1 required positional argument: 'dst'" + ] + } + ], "source": [ - "# copy docs/api .gitignore file to filter out automatically generated api yml and manifest file\n", - "# asset copied from bonsai-rx/gui \n", - "shutil.copy(os.path.join(assets_docs_api_dir, \".gitignore\"), docs_api_dir)" + "# copy docs/api folder and .gitignore file to filter out automatically generated api yml and manifest file\n", + "# asset copied from bonsai-rx/gui 4/22/24\n", + "shutil.copytree(os.path.join(assets_docs_api_dir, docs_api_dir))" ] }, { @@ -101,7 +139,7 @@ "outputs": [], "source": [ "# copy docs/build.ps1 file to export workflow images\n", - "# asset copied from bonsai-rx/gui \n", + "# asset copied from bonsai-rx/gui 4/22/24\n", "# to add - prompt for package name to modify script\n", "shutil.copy(os.path.join(assets_docs_dir, \"build.ps1\"), docs_dir)" ] @@ -113,7 +151,7 @@ "outputs": [], "source": [ "# copy docs/template folder\n", - "# asset copied from bonsai-rx/gui \n", + "# asset copied from bonsai-rx/gui 4/22/24\n", "# to add - prompt for package name to modify github link\n", "shutil.copytree(os.path.join(assets_docs_dir, \"template\"), os.path.join(docs_dir, \"template\"))" ] @@ -132,19 +170,11 @@ " pass\n", "\n", "try:\n", - " os.mkdir(docs_api_dir)\n", + " os.mkdir(docs_articles_dir)\n", "except:\n", " pass\n", "\n", - "try:\n", - " os.mkdir(docs_workflows_dir)\n", - "except:\n", - " pass\n", "\n", - "try:\n", - " os.mkdir(docs_articles_dir)\n", - "except:\n", - " pass\n", "\n" ] } From 781a7c0ec69ce1590e5f9787780a709af644abab Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Tue, 23 Apr 2024 09:23:49 -0700 Subject: [PATCH 11/35] added make images folder to copy-files script --- modules/Copy-Files.ipynb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index 073af1a..dbfc548 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -28,6 +28,7 @@ "docs_api_dir = os.path.join(docs_dir, \"api\")\n", "docs_workflows_dir = os.path.join(docs_dir, \"workflows\")\n", "docs_articles_dir = os.path.join(docs_dir, \"articles\")\n", + "docs_images_dir = os.path.join(docs_dir, \"images\")\n", "src_dir = os.path.join(root_dir, \"src\")" ] }, @@ -174,6 +175,10 @@ "except:\n", " pass\n", "\n", + "try:\n", + " os.mkdir(docs_images_dir)\n", + "except:\n", + " pass\n", "\n", "\n" ] From f1b5c97a4fca13035da6c85ae8166dafa4f30c13 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Fri, 26 Apr 2024 16:20:29 -0700 Subject: [PATCH 12/35] added Configure-Json script --- modules/Configure-Json.ipynb | 62 ++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 modules/Configure-Json.ipynb diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb new file mode 100644 index 0000000..9d5fafa --- /dev/null +++ b/modules/Configure-Json.ipynb @@ -0,0 +1,62 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# define folder constants\n", + "current_dir = os.getcwd()\n", + "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", + "docs_dir = os.path.join(root_dir,\"docs\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# load json file\n", + "try:\n", + " with open(os.path.join(docs_dir, \"docfx.json\"), 'r') as file:\n", + " data = json.load(file)\n", + " print(data)\n", + "except FileNotFoundError:\n", + " print(\"docfx.json not file, run docfx first to create docfx file\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 211048ffb9f0c229c0ce009c08b7e1b09ec71827 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Fri, 26 Apr 2024 16:42:17 -0700 Subject: [PATCH 13/35] updated configure-json script with xref and markdig extensions attributes --- modules/Configure-Json.ipynb | 46 ++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb index 9d5fafa..4506eb6 100644 --- a/modules/Configure-Json.ipynb +++ b/modules/Configure-Json.ipynb @@ -32,9 +32,51 @@ "try:\n", " with open(os.path.join(docs_dir, \"docfx.json\"), 'r') as file:\n", " data = json.load(file)\n", - " print(data)\n", "except FileNotFoundError:\n", - " print(\"docfx.json not file, run docfx first to create docfx file\")" + " print(\"docfx.json not file, run docfx first to create docfx.json file\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'data' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[4], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m data[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mbuild\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmarkdownEngineProperties\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmarkdigExtensions\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m [\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mattributes\u001b[39m\u001b[38;5;124m\"\u001b[39m,\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcustomcontainers\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n", + "\u001b[1;31mNameError\u001b[0m: name 'data' is not defined" + ] + } + ], + "source": [ + "# adds markdig extensions\n", + "data[\"build\"][\"markdownEngineProperties\"][\"markdigExtensions\"] = [\"attributes\",\"customcontainers\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# adds xref \n", + "data[\"build\"][\"xref\"] = [\"https://bonsai-rx.org/docs/xrefmap.yml\",\"https://horizongir.github.io/reactive/xrefmap.yml\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# write json file\n", + "with open(os.path.join(docs_dir, \"docfx.json\"), 'w') as file:\n", + " json.dump(data, file, indent=4)\n" ] } ], From a6a7c5eb9ca4081bf562b19c78159ad53827cdc5 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Fri, 26 Apr 2024 16:58:39 -0700 Subject: [PATCH 14/35] fix to configure-json script to address markdig extensions not working --- modules/Configure-Json.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb index 4506eb6..10ad5b6 100644 --- a/modules/Configure-Json.ipynb +++ b/modules/Configure-Json.ipynb @@ -55,7 +55,7 @@ ], "source": [ "# adds markdig extensions\n", - "data[\"build\"][\"markdownEngineProperties\"][\"markdigExtensions\"] = [\"attributes\",\"customcontainers\"]" + "data[\"build\"][\"markdownEngineProperties\"] = {\"markdigExtensions\": [\"attributes\",\"customcontainers\"]}" ] }, { @@ -76,7 +76,7 @@ "source": [ "# write json file\n", "with open(os.path.join(docs_dir, \"docfx.json\"), 'w') as file:\n", - " json.dump(data, file, indent=4)\n" + " json.dump(data, file, indent=4)" ] } ], From 3434b4dbd5609bb4a7948f1a895eee4b40abf6a1 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Fri, 26 Apr 2024 17:18:40 -0700 Subject: [PATCH 15/35] added filter.yml and template attributes and modified docfx.json output indent in configure-json script --- modules/Configure-Json.ipynb | 39 ++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb index 10ad5b6..30bb073 100644 --- a/modules/Configure-Json.ipynb +++ b/modules/Configure-Json.ipynb @@ -38,21 +38,30 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# adds filter .yml\n", + "# the structure in that attribute is a bit weird, its a dictionary in a list, so the index [0] is just calling up that dictionary\n", + "data[\"metadata\"][0][\"filter\"] = \"filter.yml\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'data' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[4], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m data[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mbuild\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmarkdownEngineProperties\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmarkdigExtensions\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m [\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mattributes\u001b[39m\u001b[38;5;124m\"\u001b[39m,\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcustomcontainers\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n", - "\u001b[1;31mNameError\u001b[0m: name 'data' is not defined" - ] - } - ], + "outputs": [], + "source": [ + "# adds bonsai templates \n", + "data[\"build\"][\"template\"].extend([\"bonsai/template\",\"template\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# adds markdig extensions\n", "data[\"build\"][\"markdownEngineProperties\"] = {\"markdigExtensions\": [\"attributes\",\"customcontainers\"]}" @@ -76,7 +85,7 @@ "source": [ "# write json file\n", "with open(os.path.join(docs_dir, \"docfx.json\"), 'w') as file:\n", - " json.dump(data, file, indent=4)" + " json.dump(data, file, indent=1)" ] } ], From 629eb4684f1d43d6c21a04414c654dc295423e61 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Fri, 26 Apr 2024 17:56:59 -0700 Subject: [PATCH 16/35] added appfooter, git contribute attributes to configure-json script --- modules/Configure-Json.ipynb | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb index 30bb073..ccb1770 100644 --- a/modules/Configure-Json.ipynb +++ b/modules/Configure-Json.ipynb @@ -36,6 +36,16 @@ " print(\"docfx.json not file, run docfx first to create docfx.json file\")" ] }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# prompt for github website\n", + "github_link = input(\"Please enter the github website\")" + ] + }, { "cell_type": "code", "execution_count": null, @@ -57,6 +67,26 @@ "data[\"build\"][\"template\"].extend([\"bonsai/template\",\"template\"])" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# adds site footer\n", + "data[\"build\"][\"globalMetadata\"][\"_appFooter\"] = \"© 2024 Bonsai Foundation CIC and Contributors. Made with docfx\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# adds git contribute section\n", + "data[\"build\"][\"globalMetadata\"][\"_gitContribute\"]={\"repo\": github_link, \"branch\": \"main\", \"apiSpecFolder\": \"apidoc\"}" + ] + }, { "cell_type": "code", "execution_count": null, @@ -85,7 +115,7 @@ "source": [ "# write json file\n", "with open(os.path.join(docs_dir, \"docfx.json\"), 'w') as file:\n", - " json.dump(data, file, indent=1)" + " json.dump(data, file, indent=2)" ] } ], From b70724c72d2082c2a15199335f8b44a5f4be41a3 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sat, 27 Apr 2024 17:31:13 -0700 Subject: [PATCH 17/35] remaining attributes app name and title added to configure-json, cleaned up code --- modules/Configure-Json.ipynb | 100 ++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 7 deletions(-) diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb index ccb1770..2154688 100644 --- a/modules/Configure-Json.ipynb +++ b/modules/Configure-Json.ipynb @@ -6,6 +6,7 @@ "metadata": {}, "outputs": [], "source": [ + "# code based on comparing bonsai.gui docfx.json file to a fresh docfx.json (updated 4/27/24)\n", "import json\n", "import os" ] @@ -52,9 +53,71 @@ "metadata": {}, "outputs": [], "source": [ - "# adds filter .yml\n", - "# the structure in that attribute is a bit weird, its a dictionary in a list, so the index [0] is just calling up that dictionary\n", - "data[\"metadata\"][0][\"filter\"] = \"filter.yml\"" + "# prompt for package name\n", + "package_name = input(\"Please enter the package name for the website - for instance ML for Bonsai.ML\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# adds filter .yml to metadata build\n", + "# the structure in the attributes is a bit weird, its a dictionary in a list, so the index [0] is just calling up that dictionary\n", + "data[\"metadata\"][0][\"filter\"] = \"filter.yml\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# adds files and folders to be excluded from site building\n", + "if \"filter.yml\" in data[\"build\"][\"content\"][0][\"exclude\"]:\n", + " pass\n", + "else:\n", + " data[\"build\"][\"content\"][0][\"exclude\"].extend(\"filter.yml\")\n", + " \n", + "if \"bonsai/**\" in data[\"build\"][\"content\"][0][\"exclude\"]:\n", + " pass\n", + "else:\n", + " data[\"build\"][\"content\"][0][\"exclude\"].extend(\"bonsai/**\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# adds site resources\n", + "if \"workflows/**\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", + " pass\n", + "else: \n", + " data[\"build\"][\"resource\"][0][\"files\"].extend[\"workflows/**\"]\n", + " \n", + "if \"logo.svg\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", + " pass\n", + "else: \n", + " data[\"build\"][\"resource\"][0][\"files\"].extend[\"logo.svg\"]\n", + "\n", + "if \"favicon.ico\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", + " pass\n", + "else: \n", + " data[\"build\"][\"resource\"][0][\"files\"].extend[\"favicon.ico\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# adds overwrite section\n", + "data[\"build\"][\"overwrite\"][0] = {\"files\":[\"apidoc/**.md\"], \n", + " \"exclude\": [\"obj/**\", \"_site/**\"]}" ] }, { @@ -64,7 +127,26 @@ "outputs": [], "source": [ "# adds bonsai templates \n", - "data[\"build\"][\"template\"].extend([\"bonsai/template\",\"template\"])" + "if \"bonsai/template\" in data[\"build\"][\"template\"]:\n", + " pass\n", + "else:\n", + " data[\"build\"][\"template\"].extend([\"bonsai/template\"])\n", + " \n", + "if \"template\" in data[\"build\"][\"template\"]:\n", + " pass\n", + "else:\n", + " data[\"build\"][\"template\"].extend([\"template\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# adds app name and website\n", + "data[\"build\"][\"globalMetadata\"][\"_appName\"] = \"Bonsai - \" + package_name\n", + "data[\"build\"][\"globalMetadata\"][\"_appTitle\"] = \"Bonsai.\" + package_name" ] }, { @@ -84,7 +166,9 @@ "outputs": [], "source": [ "# adds git contribute section\n", - "data[\"build\"][\"globalMetadata\"][\"_gitContribute\"]={\"repo\": github_link, \"branch\": \"main\", \"apiSpecFolder\": \"apidoc\"}" + "data[\"build\"][\"globalMetadata\"][\"_gitContribute\"] = {\"repo\": github_link, \n", + " \"branch\": \"main\", \n", + " \"apiSpecFolder\": \"apidoc\"}" ] }, { @@ -94,7 +178,8 @@ "outputs": [], "source": [ "# adds markdig extensions\n", - "data[\"build\"][\"markdownEngineProperties\"] = {\"markdigExtensions\": [\"attributes\",\"customcontainers\"]}" + "data[\"build\"][\"markdownEngineProperties\"] = {\"markdigExtensions\": [\"attributes\",\n", + " \"customcontainers\"]}" ] }, { @@ -104,7 +189,8 @@ "outputs": [], "source": [ "# adds xref \n", - "data[\"build\"][\"xref\"] = [\"https://bonsai-rx.org/docs/xrefmap.yml\",\"https://horizongir.github.io/reactive/xrefmap.yml\"]" + "data[\"build\"][\"xref\"] = [\"https://bonsai-rx.org/docs/xrefmap.yml\",\n", + " \"https://horizongir.github.io/reactive/xrefmap.yml\"]" ] }, { From 28b57f4d8a96e0bdaaf89540ddbcab6dcad6add8 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sat, 27 Apr 2024 17:38:46 -0700 Subject: [PATCH 18/35] bug fixes to configure-json --- modules/Configure-Json.ipynb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb index 2154688..b3d2e61 100644 --- a/modules/Configure-Json.ipynb +++ b/modules/Configure-Json.ipynb @@ -96,17 +96,17 @@ "if \"workflows/**\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", " pass\n", "else: \n", - " data[\"build\"][\"resource\"][0][\"files\"].extend[\"workflows/**\"]\n", + " data[\"build\"][\"resource\"][0][\"files\"].extend(\"workflows/**\")\n", " \n", "if \"logo.svg\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", " pass\n", "else: \n", - " data[\"build\"][\"resource\"][0][\"files\"].extend[\"logo.svg\"]\n", + " data[\"build\"][\"resource\"][0][\"files\"].extend(\"logo.svg\")\n", "\n", "if \"favicon.ico\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", " pass\n", "else: \n", - " data[\"build\"][\"resource\"][0][\"files\"].extend[\"favicon.ico\"]" + " data[\"build\"][\"resource\"][0][\"files\"].extend(\"favicon.ico\")" ] }, { @@ -130,12 +130,12 @@ "if \"bonsai/template\" in data[\"build\"][\"template\"]:\n", " pass\n", "else:\n", - " data[\"build\"][\"template\"].extend([\"bonsai/template\"])\n", + " data[\"build\"][\"template\"].extend(\"bonsai/template\")\n", " \n", "if \"template\" in data[\"build\"][\"template\"]:\n", " pass\n", "else:\n", - " data[\"build\"][\"template\"].extend([\"template\"])" + " data[\"build\"][\"template\"].extend(\"template\")" ] }, { From ab9fee1416ec9c7130f70cd97af30cfe6f2e8101 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sat, 27 Apr 2024 17:43:33 -0700 Subject: [PATCH 19/35] bug fixes to overwrite section of configure-json --- modules/Configure-Json.ipynb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb index b3d2e61..07f9fd3 100644 --- a/modules/Configure-Json.ipynb +++ b/modules/Configure-Json.ipynb @@ -116,8 +116,11 @@ "outputs": [], "source": [ "# adds overwrite section\n", - "data[\"build\"][\"overwrite\"][0] = {\"files\":[\"apidoc/**.md\"], \n", - " \"exclude\": [\"obj/**\", \"_site/**\"]}" + "# data[\"build\"][\"overwrite\"][0] = {\"files\":[\"apidoc/**.md\"], \n", + "# \"exclude\": [\"obj/**\", \"_site/**\"]}\n", + "\n", + "data[\"build\"][\"overwrite\"] = [{\"files\":[\"apidoc/**.md\"], \n", + " \"exclude\": [\"obj/**\", \"_site/**\"]}]" ] }, { From 619f6b15f2e4039c1eeb8e3896a3f37f0bf51618 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sat, 27 Apr 2024 17:49:27 -0700 Subject: [PATCH 20/35] bug fixes to list extend functions in configure-json --- modules/Configure-Json.ipynb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb index 07f9fd3..14b5dab 100644 --- a/modules/Configure-Json.ipynb +++ b/modules/Configure-Json.ipynb @@ -78,12 +78,12 @@ "if \"filter.yml\" in data[\"build\"][\"content\"][0][\"exclude\"]:\n", " pass\n", "else:\n", - " data[\"build\"][\"content\"][0][\"exclude\"].extend(\"filter.yml\")\n", + " data[\"build\"][\"content\"][0][\"exclude\"].extend([\"filter.yml\"])\n", " \n", "if \"bonsai/**\" in data[\"build\"][\"content\"][0][\"exclude\"]:\n", " pass\n", "else:\n", - " data[\"build\"][\"content\"][0][\"exclude\"].extend(\"bonsai/**\")" + " data[\"build\"][\"content\"][0][\"exclude\"].extend([\"bonsai/**\"])" ] }, { @@ -96,17 +96,17 @@ "if \"workflows/**\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", " pass\n", "else: \n", - " data[\"build\"][\"resource\"][0][\"files\"].extend(\"workflows/**\")\n", + " data[\"build\"][\"resource\"][0][\"files\"].extend([\"workflows/**\"])\n", " \n", "if \"logo.svg\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", " pass\n", "else: \n", - " data[\"build\"][\"resource\"][0][\"files\"].extend(\"logo.svg\")\n", + " data[\"build\"][\"resource\"][0][\"files\"].extend([\"logo.svg\"])\n", "\n", "if \"favicon.ico\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", " pass\n", "else: \n", - " data[\"build\"][\"resource\"][0][\"files\"].extend(\"favicon.ico\")" + " data[\"build\"][\"resource\"][0][\"files\"].extend([\"favicon.ico\"])" ] }, { From 7e183c785eb3549056e6a5077d03022ec475523a Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sat, 27 Apr 2024 17:52:47 -0700 Subject: [PATCH 21/35] additional bug fixes to list extend functions in configure-json --- modules/Configure-Json.ipynb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb index 14b5dab..b6df997 100644 --- a/modules/Configure-Json.ipynb +++ b/modules/Configure-Json.ipynb @@ -65,7 +65,7 @@ "source": [ "# adds filter .yml to metadata build\n", "# the structure in the attributes is a bit weird, its a dictionary in a list, so the index [0] is just calling up that dictionary\n", - "data[\"metadata\"][0][\"filter\"] = \"filter.yml\"\n" + "data[\"metadata\"][0][\"filter\"] = \"filter.yml\"" ] }, { @@ -116,9 +116,6 @@ "outputs": [], "source": [ "# adds overwrite section\n", - "# data[\"build\"][\"overwrite\"][0] = {\"files\":[\"apidoc/**.md\"], \n", - "# \"exclude\": [\"obj/**\", \"_site/**\"]}\n", - "\n", "data[\"build\"][\"overwrite\"] = [{\"files\":[\"apidoc/**.md\"], \n", " \"exclude\": [\"obj/**\", \"_site/**\"]}]" ] @@ -133,12 +130,12 @@ "if \"bonsai/template\" in data[\"build\"][\"template\"]:\n", " pass\n", "else:\n", - " data[\"build\"][\"template\"].extend(\"bonsai/template\")\n", + " data[\"build\"][\"template\"].extend([\"bonsai/template\"])\n", " \n", "if \"template\" in data[\"build\"][\"template\"]:\n", " pass\n", "else:\n", - " data[\"build\"][\"template\"].extend(\"template\")" + " data[\"build\"][\"template\"].extend([\"template\"])" ] }, { From c6bb339ccf5ded7da779ba329d8144bdbb321f77 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sat, 27 Apr 2024 18:17:55 -0700 Subject: [PATCH 22/35] added filter.yml and rearranged sections in copy-files --- assets/docs/filter.yml | 4 ++ modules/Copy-Files.ipynb | 123 +++++++++++++++++++-------------------- 2 files changed, 65 insertions(+), 62 deletions(-) create mode 100644 assets/docs/filter.yml diff --git a/assets/docs/filter.yml b/assets/docs/filter.yml new file mode 100644 index 0000000..3d3d6c9 --- /dev/null +++ b/assets/docs/filter.yml @@ -0,0 +1,4 @@ +apiRules: +- exclude: + hasAttribute: + uid: System.ObsoleteAttribute \ No newline at end of file diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index dbfc548..08a4320 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -6,6 +6,8 @@ "metadata": {}, "outputs": [], "source": [ + "# Although it might be easier to just copy the entire asset directory, the current format allows selective copying \n", + "# so as to not overwrite existing files (if they exist)\n", "import os\n", "import shutil" ] @@ -34,24 +36,26 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'c:\\\\Users\\\\shawn\\\\docs'" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "# copy docs .gitignore file to filter out _site folder\n", - "# asset copied from bonsai-rx/gui 4/22/24\n", - "shutil.copy(os.path.join(assets_docs_dir, \".gitignore\"), docs_dir)" + "# make folders for docfx\n", + "# try except blocks in case folder already exists\n", + "try:\n", + " os.mkdir(docs_dir)\n", + "except:\n", + " pass\n", + "\n", + "try:\n", + " os.mkdir(docs_articles_dir)\n", + "except:\n", + " pass\n", + "\n", + "try:\n", + " os.mkdir(docs_images_dir)\n", + "except:\n", + " pass" ] }, { @@ -71,22 +75,11 @@ } ], "source": [ - "# copy .bonsai folder for making bonsai env\n", + "# copy root/.bonsai folder for making bonsai env\n", "# asset copied from bonsai-rx/gui 4/22/24\n", "shutil.copytree(os.path.join(assets_root_dir, \".bonsai\"), os.path.join(root_dir, \".bonsai\"))" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# copy docs/workflows folder\n", - "# asset copied from bonsai-rx/gui 4/23/24\n", - "shutil.copytree(assets_workflows_dir, docs_workflows_dir)" - ] - }, { "cell_type": "code", "execution_count": 6, @@ -104,7 +97,7 @@ } ], "source": [ - "# copy .github folder for github actions\n", + "# copy root/.github folder for github actions\n", "# asset copied from bonsai-rx/gui 4/22/24\n", "# to add - prompt for package name to modify github actions scripts\n", "shutil.copytree(os.path.join(assets_root_dir, \".github\"), os.path.join(root_dir, \".github\"))" @@ -112,25 +105,35 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 4, "metadata": {}, "outputs": [ { - "ename": "TypeError", - "evalue": "copytree() missing 1 required positional argument: 'dst'", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[7], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# copy docs/api folder and .gitignore file to filter out automatically generated api yml and manifest file\u001b[39;00m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;66;03m# asset copied from bonsai-rx/gui 4/22/24\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m shutil\u001b[38;5;241m.\u001b[39mcopytree(os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mjoin(assets_docs_api_dir, docs_api_dir))\n", - "\u001b[1;31mTypeError\u001b[0m: copytree() missing 1 required positional argument: 'dst'" - ] + "data": { + "text/plain": [ + "'c:\\\\Users\\\\shawn\\\\docs'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "# copy docs/api folder and .gitignore file to filter out automatically generated api yml and manifest file\n", + "# copy docs .gitignore to filter out _site folder\n", "# asset copied from bonsai-rx/gui 4/22/24\n", - "shutil.copytree(os.path.join(assets_docs_api_dir, docs_api_dir))" + "shutil.copy(os.path.join(assets_docs_dir, \".gitignore\"), docs_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# copy docs filter.yml to filter out obsolete attributes\n", + "# asset copied from bonsai-rx/gui 4/27/24\n", + "shutil.copy(os.path.join(assets_docs_dir, \"filter.yml\"), docs_dir)\n" ] }, { @@ -151,10 +154,20 @@ "metadata": {}, "outputs": [], "source": [ - "# copy docs/template folder\n", + "# copy docs/workflows folder\n", + "# asset copied from bonsai-rx/gui 4/23/24\n", + "shutil.copytree(assets_workflows_dir, docs_workflows_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# copy docs/api folder and .gitignore file to filter out automatically generated api yml and manifest file\n", "# asset copied from bonsai-rx/gui 4/22/24\n", - "# to add - prompt for package name to modify github link\n", - "shutil.copytree(os.path.join(assets_docs_dir, \"template\"), os.path.join(docs_dir, \"template\"))" + "shutil.copytree(assets_docs_api_dir, docs_api_dir)" ] }, { @@ -163,24 +176,10 @@ "metadata": {}, "outputs": [], "source": [ - "# make folders for docfx\n", - "# try except blocks in case folder alreaady exists\n", - "try:\n", - " os.mkdir(docs_dir)\n", - "except:\n", - " pass\n", - "\n", - "try:\n", - " os.mkdir(docs_articles_dir)\n", - "except:\n", - " pass\n", - "\n", - "try:\n", - " os.mkdir(docs_images_dir)\n", - "except:\n", - " pass\n", - "\n", - "\n" + "# copy docs/template folder\n", + "# asset copied from bonsai-rx/gui 4/22/24\n", + "# to add - prompt for package name to modify github link\n", + "shutil.copytree(os.path.join(assets_docs_dir, \"template\"), os.path.join(docs_dir, \"template\"))" ] } ], From 8ddb45cfbd63e1a1557b2f5028c37c2b285b1cd2 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sun, 28 Apr 2024 11:15:04 -0700 Subject: [PATCH 23/35] added favicon and logo.svg, started code to modify package specific stuff --- assets/docs/favicon.ico | Bin 0 -> 113038 bytes assets/docs/logo.svg | 96 +++++++++++++++++++++++++++++++++++++++ modules/Copy-Files.ipynb | 20 ++++++-- 3 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 assets/docs/favicon.ico create mode 100644 assets/docs/logo.svg diff --git a/assets/docs/favicon.ico b/assets/docs/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5387c2df21da5a4d5118dd88f7c2604f72d47d7b GIT binary patch literal 113038 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 + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index 08a4320..9f29e41 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -6,8 +6,8 @@ "metadata": {}, "outputs": [], "source": [ - "# Although it might be easier to just copy the entire asset directory, the current format allows selective copying \n", - "# so as to not overwrite existing files (if they exist)\n", + "# Although it might be easier to just copy the entire assets directory, the current format allows selective copying \n", + "# and avoids FileExistsErrors \n", "import os\n", "import shutil" ] @@ -125,6 +125,18 @@ "shutil.copy(os.path.join(assets_docs_dir, \".gitignore\"), docs_dir)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# copy docs favicon and site logo\n", + "# asset copied from bonsai-rx/gui 4/28/24\n", + "shutil.copy(os.path.join(assets_docs_dir, \"favicon.ico\"), docs_dir)\n", + "shutil.copy(os.path.join(assets_docs_dir, \"logo.svg\"), docs_dir)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -145,7 +157,9 @@ "# copy docs/build.ps1 file to export workflow images\n", "# asset copied from bonsai-rx/gui 4/22/24\n", "# to add - prompt for package name to modify script\n", - "shutil.copy(os.path.join(assets_docs_dir, \"build.ps1\"), docs_dir)" + "shutil.copy(os.path.join(assets_docs_dir, \"build.ps1\"), docs_dir)\n", + "with open(os.path.join(docs_dir,\"build.ps1\"), 'r') as file:\n", + " script_content = file.read()\n" ] }, { From b99876cf2f5714ca7e39edc502f776879e9c6ac1 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sun, 28 Apr 2024 14:31:11 -0700 Subject: [PATCH 24/35] added replacement of package location and github link in build.ps1 and templates --- assets/root/.github/workflows/docs.yml | 2 +- modules/Copy-Files.ipynb | 43 +++++++++++++++++++++----- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/assets/root/.github/workflows/docs.yml b/assets/root/.github/workflows/docs.yml index 57248ef..2ccd282 100644 --- a/assets/root/.github/workflows/docs.yml +++ b/assets/root/.github/workflows/docs.yml @@ -22,7 +22,7 @@ jobs: uses: microsoft/setup-msbuild@v2 - name: Restore NuGet Packages - run: msbuild -t:restore src\Bonsai.Gui.sln + run: msbuild -t:restore src/Bonsai.Gui.sln - name: Build Solution run: msbuild src/Bonsai.Gui.sln /p:Configuration=Release diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index 9f29e41..c7a304b 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -7,9 +7,10 @@ "outputs": [], "source": [ "# Although it might be easier to just copy the entire assets directory, the current format allows selective copying \n", - "# and avoids FileExistsErrors \n", + "# and avoids FileExistsErrors from breaking the entire run\n", "import os\n", - "import shutil" + "import shutil\n", + "import re" ] }, { @@ -154,12 +155,23 @@ "metadata": {}, "outputs": [], "source": [ - "# copy docs/build.ps1 file to export workflow images\n", + "# copy docs/build.ps1 file to export workflow images and modifies script to handle new package\n", "# asset copied from bonsai-rx/gui 4/22/24\n", - "# to add - prompt for package name to modify script\n", + "# to add - automatically search for package location \n", + "\n", "shutil.copy(os.path.join(assets_docs_dir, \"build.ps1\"), docs_dir)\n", + "\n", + "new_package_src = \"..\\\\\" + input(\"Please enter the location of the package bin e.g src\\Bonsai.Gui.ZedGraph\\bin\\Release\\net472\")\n", "with open(os.path.join(docs_dir,\"build.ps1\"), 'r') as file:\n", - " script_content = file.read()\n" + " file_content = file.readlines()\n", + " for line in file_content:\n", + " # line replacement is done in 2 steps due to a bug in re.sub not accepting strings without escape characters\n", + " new_line = re.sub(r'\"([^\"]*)\"', '\"text_to_replace\"', line)\n", + " new_line = new_line.replace(\"text_to_replace\", new_package_src)\n", + " file_content[0] = new_line\n", + " with open(os.path.join(docs_dir,\"build.ps1\"), 'w') as new_file:\n", + " new_file.writelines(file_content)\n", + " break" ] }, { @@ -192,8 +204,25 @@ "source": [ "# copy docs/template folder\n", "# asset copied from bonsai-rx/gui 4/22/24\n", - "# to add - prompt for package name to modify github link\n", - "shutil.copytree(os.path.join(assets_docs_dir, \"template\"), os.path.join(docs_dir, \"template\"))" + "\n", + "shutil.copytree(os.path.join(assets_docs_dir, \"template\"), os.path.join(docs_dir, \"template\"))\n", + "\n", + "new_package_github = input(\"Please enter the github link for the new package\")\n", + "with open(os.path.join(docs_dir,\"template\", \"public\", \"main.js\"), 'r') as file:\n", + " file_content = file.readlines()\n", + " line_position = -1\n", + " for line in file_content:\n", + " line_position += 1\n", + " if \"href\" in line:\n", + " # line replacement is done in 2 steps due to a bug in re.sub not accepting strings without escape characters\n", + " new_line = re.sub(r\"'([^']*)'\", \"'text_to_replace'\", line)\n", + " new_line = new_line.replace(\"text_to_replace\", new_package_github)\n", + " file_content[line_position] = new_line\n", + " with open(os.path.join(docs_dir,\"template\", \"public\", \"main.js\"), 'w') as new_file:\n", + " new_file.writelines(file_content)\n", + " break\n", + " else:\n", + " pass" ] } ], From 8ee007b4df24915b7011688c31cfdd145ac42881 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Sun, 28 Apr 2024 15:34:50 -0700 Subject: [PATCH 25/35] added replacement of src sln file in github actions workflows --- modules/Copy-Files.ipynb | 44 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb index c7a304b..92b68ed 100644 --- a/modules/Copy-Files.ipynb +++ b/modules/Copy-Files.ipynb @@ -8,6 +8,7 @@ "source": [ "# Although it might be easier to just copy the entire assets directory, the current format allows selective copying \n", "# and avoids FileExistsErrors from breaking the entire run\n", + "# might also want to look into refactoring the regex replacement code as a function since its being used quite often\n", "import os\n", "import shutil\n", "import re" @@ -100,8 +101,47 @@ "source": [ "# copy root/.github folder for github actions\n", "# asset copied from bonsai-rx/gui 4/22/24\n", - "# to add - prompt for package name to modify github actions scripts\n", - "shutil.copytree(os.path.join(assets_root_dir, \".github\"), os.path.join(root_dir, \".github\"))" + "# to add - automatically search for src sln file\n", + "shutil.copytree(os.path.join(assets_root_dir, \".github\"), os.path.join(root_dir, \".github\"))\n", + "\n", + "new_package_src_sln = input(\"Please enter the location of the package src sln file e.g src/Bonsai.Gui.sln\")\n", + "with open(os.path.join(root_dir, \".github\", \"workflows\", \"build.yml\"), 'r') as file:\n", + " file_content = file.readlines()\n", + " line_position = -1\n", + " for line in file_content:\n", + " line_position += 1\n", + " if \"nuget restore\" in line:\n", + " # line replacement is done in 2 steps due to a bug in re.sub not accepting strings without escape characters\n", + " new_line = re.sub(r\"src/[^/]+\\.sln\", \"text_to_replace\", line)\n", + " new_line = new_line.replace(\"text_to_replace\", new_package_src_sln)\n", + " file_content[line_position] = new_line\n", + " elif \"Configuration=Release\" in line:\n", + " new_line = re.sub(r\"src/[^/]+\\.sln\", \"text_to_replace\", line)\n", + " new_line = new_line.replace(\"text_to_replace\", new_package_src_sln)\n", + " file_content[line_position] = new_line\n", + " else:\n", + " pass\n", + " with open(os.path.join(root_dir, \".github\", \"workflows\", \"build.yml\"), 'w') as new_file:\n", + " new_file.writelines(file_content)\n", + "\n", + "with open(os.path.join(root_dir, \".github\", \"workflows\", \"docs.yml\"), 'r') as file:\n", + " file_content = file.readlines()\n", + " line_position = -1\n", + " for line in file_content:\n", + " line_position += 1\n", + " if \"-t:restore\" in line:\n", + " # line replacement is done in 2 steps due to a bug in re.sub not accepting strings without escape characters\n", + " new_line = re.sub(r\"src/[^/]+\\.sln\", \"text_to_replace\", line)\n", + " new_line = new_line.replace(\"text_to_replace\", new_package_src_sln)\n", + " file_content[line_position] = new_line\n", + " elif \"Configuration=Release\" in line:\n", + " new_line = re.sub(r\"src/[^/]+\\.sln\", \"text_to_replace\", line)\n", + " new_line = new_line.replace(\"text_to_replace\", new_package_src_sln)\n", + " file_content[line_position] = new_line\n", + " else:\n", + " pass\n", + " with open(os.path.join(root_dir, \".github\", \"workflows\", \"docs.yml\"), 'w') as new_file:\n", + " new_file.writelines(file_content)" ] }, { From 79cedf3b84ebd09d6f8baf08ebab545fd5899336 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Tue, 30 Apr 2024 16:12:22 -0700 Subject: [PATCH 26/35] updated readme.md to document the new configure json and copy files script --- README.md | 7 ++++++- modules/Configure-Json.ipynb | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e00eb49..122dcf9 100644 --- a/README.md +++ b/README.md @@ -49,4 +49,9 @@ Exporting SVG images for all example workflows can be automated by placing all ` ```ps1 .\modules\Export-Image.ps1 "..\src\PackageName\bin\Release\net472" -``` \ No newline at end of file +``` + +## Python Notebooks + +This repository also provides two helper python notebooks to help configure Docfx.json as well as to copy the necessary files and folders for building a new Docfx website. +These notebooks need a base python 3 installation only and no external libraries need to be installed (other than Jupyter Notebook). diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb index b6df997..fc46958 100644 --- a/modules/Configure-Json.ipynb +++ b/modules/Configure-Json.ipynb @@ -7,6 +7,7 @@ "outputs": [], "source": [ "# code based on comparing bonsai.gui docfx.json file to a fresh docfx.json (updated 4/27/24)\n", + "# might be easier to just copy the docfx.json file but it might change when docfx is updated.\n", "import json\n", "import os" ] From a1768e3bf3343cfb4f7f397e59ec549d64cf07d4 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Thu, 11 Jul 2024 15:49:07 -0700 Subject: [PATCH 27/35] add export-individual-node-workflow script for API docs --- .../Export-Individual-Node-Workflows.ipynb | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 modules/Export-Individual-Node-Workflows.ipynb diff --git a/modules/Export-Individual-Node-Workflows.ipynb b/modules/Export-Individual-Node-Workflows.ipynb new file mode 100644 index 0000000..3fcd09c --- /dev/null +++ b/modules/Export-Individual-Node-Workflows.ipynb @@ -0,0 +1,151 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# import libraries\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [], + "source": [ + "# function to extract operator names, location, and namespace from a given source folder\n", + "def extract_operator_names_location(directory):\n", + " file_list = []\n", + " operator_list = []\n", + " for root, dirs, files in os.walk(directory):\n", + " for file in files:\n", + " if file.endswith(\"cs\"):\n", + " # skips .cs files in debug and release folder that arent Bonsai operators\n", + " # some operators (for instance NumpyHelper and TimeSeriesOxyPlotBase) do not show up in API docs but nsure why\n", + " if \"Release\" not in root:\n", + " if \"Debug\" not in root:\n", + " if \"Properties\" not in root:\n", + " operator_property_list = []\n", + " file_list.append(os.path.join(root, file))\n", + " operator_list.append(file[:-3])\n", + " operator_dictionary = {operator_list[i]: [file_list[i]] for i in range(len(file_list))}\n", + " return operator_dictionary" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "# define folder constants\n", + "current_dir = os.getcwd()\n", + "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", + "docs_dir = os.path.join(root_dir,\"docs\")\n", + "src_dir = os.path.join(root_dir, \"src\")" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [], + "source": [ + "# extract operator dictionary containing operator name as a key and a tuple value with location and namespace)\n", + "operator_dictionary = extract_operator_names_location(src_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ChannelTriggers ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ChannelTriggers.cs', 'Bonsai.PulsePal', ['ChannelTriggers']]\n", + "CombinatorTypeConverter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CombinatorTypeConverter.cs', 'Bonsai.PulsePal', []]\n", + "ConfigureChannelParameter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureChannelParameter.cs', 'Bonsai.PulsePal', ['DeviceName', 'Parameter']]\n", + "ConfigureOutputChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureOutputChannel.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", + "ConfigureTriggerChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureTriggerChannel.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", + "CreatePulsePal ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CreatePulsePal.cs', 'Bonsai.PulsePal', ['DeviceName', 'PortName', 'OutputChannels', 'TriggerChannels']]\n", + "CustomPulseTrain ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomPulseTrain.cs', 'Bonsai.PulsePal', []]\n", + "CustomTrainId ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomTrainId.cs', 'Bonsai.PulsePal', ['CustomTrainId']]\n", + "CustomTrainTarget ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomTrainTarget.cs', 'Bonsai.PulsePal', ['CustomTrainTarget']]\n", + "DeviceNameConverter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\DeviceNameConverter.cs', 'Bonsai.PulsePal', []]\n", + "OutputChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\OutputChannel.cs', 'Bonsai.PulsePal', ['OutputChannel']]\n", + "ParameterCode ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ParameterCode.cs', 'Bonsai.PulsePal', []]\n", + "PolymorphicCombinator ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PolymorphicCombinator.cs', 'Bonsai.PulsePal', ['descr)']]\n", + "PulseOnset ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulseOnset.cs', 'Bonsai.PulsePal', ['Time', 'Voltage']]\n", + "PulsePalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalConfiguration.cs', 'Bonsai.PulsePal', ['PortName']]\n", + "PulsePalDevice ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalDevice.cs', 'Bonsai.PulsePal', ['FirmwareVersion', 'IsOpen', 'pulsePal)']]\n", + "PulsePalDisposable ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalDisposable.cs', 'Bonsai.PulsePal', ['pulsePal,', 'PulsePal', 'IsDisposed']]\n", + "PulsePalManager ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalManager.cs', 'Bonsai.PulsePal', []]\n", + "SendCustomPulseTrain ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SendCustomPulseTrain.cs', 'Bonsai.PulsePal', ['DeviceName', 'CustomTrainIdentity']]\n", + "SendCustomWaveform ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SendCustomWaveform.cs', 'Bonsai.PulsePal', ['DeviceName', 'CustomTrainIdentity', 'SamplingPeriod']]\n", + "SetFixedVoltage ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SetFixedVoltage.cs', 'Bonsai.PulsePal', ['DeviceName', 'Channel', 'Voltage']]\n", + "TriggerChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerChannel.cs', 'Bonsai.PulsePal', ['TriggerChannel']]\n", + "TriggerMode ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerMode.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", + "TriggerOutputChannels ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerOutputChannels.cs', 'Bonsai.PulsePal', ['DeviceName', 'Channels']]\n", + "UpdateDisplay ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\UpdateDisplay.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", + "BiphasicConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\BiphasicConfiguration.cs', 'Bonsai.PulsePal', ['Biphasic']]\n", + "BurstDurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\BurstDurationConfiguration.cs', 'Bonsai.PulsePal', ['BurstDuration']]\n", + "ChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\ChannelParameterConfiguration.cs', 'Bonsai.PulsePal', []]\n", + "ContinuousLoopConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\ContinuousLoopConfiguration.cs', 'Bonsai.PulsePal', ['ContinuousLoop']]\n", + "CustomTrainIdentityConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainIdentityConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainIdentity']]\n", + "CustomTrainLoopConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainLoopConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainLoop']]\n", + "CustomTrainTargetConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainTargetConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainTarget']]\n", + "InterBurstIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterBurstIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterBurstInterval']]\n", + "InterPhaseIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterPhaseIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterPhaseInterval']]\n", + "InterPulseIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterPulseIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterPulseInterval']]\n", + "OutputChannelConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelConfiguration.cs', 'Bonsai.PulsePal', ['Biphasic', 'Phase1Voltage', 'Phase2Voltage', 'RestingVoltage', 'PulseTrainDelay', 'Phase1Duration', 'InterPhaseInterval', 'Phase2Duration', 'InterPulseInterval', 'BurstDuration', 'InterBurstInterval', 'PulseTrainDuration', 'CustomTrainIdentity', 'CustomTrainTarget', 'CustomTrainLoop', 'TriggerOnChannel1', 'TriggerOnChannel2', 'ContinuousLoop']]\n", + "OutputChannelConfigurationCollection ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelConfigurationCollection.cs', 'Bonsai.PulsePal', []]\n", + "OutputChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelParameterConfiguration.cs', 'Bonsai.PulsePal', ['Channel']]\n", + "Phase1DurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase1DurationConfiguration.cs', 'Bonsai.PulsePal', ['Phase1Duration']]\n", + "Phase1VoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase1VoltageConfiguration.cs', 'Bonsai.PulsePal', ['Phase1Voltage']]\n", + "Phase2DurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase2DurationConfiguration.cs', 'Bonsai.PulsePal', ['Phase2Duration']]\n", + "Phase2VoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase2VoltageConfiguration.cs', 'Bonsai.PulsePal', ['Phase2Voltage']]\n", + "PulseTrainDelayConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\PulseTrainDelayConfiguration.cs', 'Bonsai.PulsePal', ['PulseTrainDelay']]\n", + "PulseTrainDurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\PulseTrainDurationConfiguration.cs', 'Bonsai.PulsePal', ['PulseTrainDuration']]\n", + "RestingVoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\RestingVoltageConfiguration.cs', 'Bonsai.PulsePal', ['RestingVoltage']]\n", + "TriggerChannelConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelConfiguration.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", + "TriggerChannelConfigurationCollection ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelConfigurationCollection.cs', 'Bonsai.PulsePal', []]\n", + "TriggerChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelParameterConfiguration.cs', 'Bonsai.PulsePal', ['Channel']]\n", + "TriggerModeConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerModeConfiguration.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", + "TriggerOnChannel1Configuration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerOnChannel1Configuration.cs', 'Bonsai.PulsePal', ['TriggerOnChannel1']]\n", + "TriggerOnChannel2Configuration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerOnChannel2Configuration.cs', 'Bonsai.PulsePal', ['TriggerOnChannel2']]\n" + ] + } + ], + "source": [ + "for key, value in operator_dictionary.items():\n", + " print(key, value)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From f55833dc55ccda173b8bd5255ac0a455e571b8d1 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 16 Sep 2024 15:44:20 -0700 Subject: [PATCH 28/35] Separate configure-json script from the rest --- README.md | 9 +- assets/docs/.gitignore | 1 - assets/docs/api/.gitignore | 3 - assets/docs/build.ps1 | 2 - assets/docs/favicon.ico | Bin 113038 -> 0 bytes assets/docs/filter.yml | 4 - assets/docs/logo.svg | 96 ------ assets/docs/template/public/main.css | 1 - assets/docs/template/public/main.js | 13 - assets/docs/workflows/.gitignore | 2 - assets/root/.bonsai/.gitignore | 3 - assets/root/.bonsai/Bonsai.config | 49 --- assets/root/.bonsai/NuGet.config | 8 - assets/root/.bonsai/Setup.cmd | 4 - assets/root/.bonsai/Setup.ps1 | 21 -- assets/root/.github/workflows/build.yml | 28 -- assets/root/.github/workflows/docs.yml | 51 --- modules/Copy-Files.ipynb | 290 ------------------ .../Export-Individual-Node-Workflows.ipynb | 151 --------- modules/export-xref.ipynb | 195 ------------ 20 files changed, 6 insertions(+), 925 deletions(-) delete mode 100644 assets/docs/.gitignore delete mode 100644 assets/docs/api/.gitignore delete mode 100644 assets/docs/build.ps1 delete mode 100644 assets/docs/favicon.ico delete mode 100644 assets/docs/filter.yml delete mode 100644 assets/docs/logo.svg delete mode 100644 assets/docs/template/public/main.css delete mode 100644 assets/docs/template/public/main.js delete mode 100644 assets/docs/workflows/.gitignore delete mode 100644 assets/root/.bonsai/.gitignore delete mode 100644 assets/root/.bonsai/Bonsai.config delete mode 100644 assets/root/.bonsai/NuGet.config delete mode 100644 assets/root/.bonsai/Setup.cmd delete mode 100644 assets/root/.bonsai/Setup.ps1 delete mode 100644 assets/root/.github/workflows/build.yml delete mode 100644 assets/root/.github/workflows/docs.yml delete mode 100644 modules/Copy-Files.ipynb delete mode 100644 modules/Export-Individual-Node-Workflows.ipynb delete mode 100644 modules/export-xref.ipynb diff --git a/README.md b/README.md index 122dcf9..26e534e 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,10 @@ Exporting SVG images for all example workflows can be automated by placing all ` .\modules\Export-Image.ps1 "..\src\PackageName\bin\Release\net472" ``` -## Python Notebooks +## Configure Json -This repository also provides two helper python notebooks to help configure Docfx.json as well as to copy the necessary files and folders for building a new Docfx website. -These notebooks need a base python 3 installation only and no external libraries need to be installed (other than Jupyter Notebook). +This script modifies `docfx.json` to reproduce the customisation options that are most frequently applied for Bonsai package documentation websites. Call the script with the following command and enter details when prompted: + +```ps1 +python .\modules\Configure-Json.py +``` \ No newline at end of file diff --git a/assets/docs/.gitignore b/assets/docs/.gitignore deleted file mode 100644 index c08f9ad..0000000 --- a/assets/docs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -_site \ No newline at end of file diff --git a/assets/docs/api/.gitignore b/assets/docs/api/.gitignore deleted file mode 100644 index adc91e4..0000000 --- a/assets/docs/api/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# auto-generated files -*.yml -.manifest \ No newline at end of file diff --git a/assets/docs/build.ps1 b/assets/docs/build.ps1 deleted file mode 100644 index 9d1d453..0000000 --- a/assets/docs/build.ps1 +++ /dev/null @@ -1,2 +0,0 @@ -.\bonsai\modules\Export-Image.ps1 "..\src\Bonsai.Gui.ZedGraph\bin\Release\net472" -dotnet docfx @args \ No newline at end of file diff --git a/assets/docs/favicon.ico b/assets/docs/favicon.ico deleted file mode 100644 index 5387c2df21da5a4d5118dd88f7c2604f72d47d7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113038 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 - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/assets/docs/template/public/main.css b/assets/docs/template/public/main.css deleted file mode 100644 index ee56505..0000000 --- a/assets/docs/template/public/main.css +++ /dev/null @@ -1 +0,0 @@ -@import "workflow.css"; \ No newline at end of file diff --git a/assets/docs/template/public/main.js b/assets/docs/template/public/main.js deleted file mode 100644 index fa1294e..0000000 --- a/assets/docs/template/public/main.js +++ /dev/null @@ -1,13 +0,0 @@ -import WorkflowContainer from "./workflow.js" - -export default { - defaultTheme: 'light', - iconLinks: [{ - icon: 'github', - href: 'https://github.com/bonsai-rx/gui', - title: 'GitHub' - }], - start: () => { - WorkflowContainer.init(); - } -} \ No newline at end of file diff --git a/assets/docs/workflows/.gitignore b/assets/docs/workflows/.gitignore deleted file mode 100644 index af455cb..0000000 --- a/assets/docs/workflows/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.layout -*.svg \ No newline at end of file diff --git a/assets/root/.bonsai/.gitignore b/assets/root/.bonsai/.gitignore deleted file mode 100644 index 16e6b2f..0000000 --- a/assets/root/.bonsai/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.exe -*.exe.* -Packages \ No newline at end of file diff --git a/assets/root/.bonsai/Bonsai.config b/assets/root/.bonsai/Bonsai.config deleted file mode 100644 index e85ebbb..0000000 --- a/assets/root/.bonsai/Bonsai.config +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/root/.bonsai/NuGet.config b/assets/root/.bonsai/NuGet.config deleted file mode 100644 index 97e8b73..0000000 --- a/assets/root/.bonsai/NuGet.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/assets/root/.bonsai/Setup.cmd b/assets/root/.bonsai/Setup.cmd deleted file mode 100644 index 92d983d..0000000 --- a/assets/root/.bonsai/Setup.cmd +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -pushd %~dp0 -powershell -ExecutionPolicy Bypass -File ./Setup.ps1 -popd \ No newline at end of file diff --git a/assets/root/.bonsai/Setup.ps1 b/assets/root/.bonsai/Setup.ps1 deleted file mode 100644 index 01cfba6..0000000 --- a/assets/root/.bonsai/Setup.ps1 +++ /dev/null @@ -1,21 +0,0 @@ -Push-Location $PSScriptRoot -if (!(Test-Path "./Bonsai.exe")) { - $release = "https://github.com/bonsai-rx/bonsai/releases/latest/download/Bonsai.zip" - $configPath = "./Bonsai.config" - if (Test-Path $configPath) { - [xml]$config = Get-Content $configPath - $bootstrapper = $config.PackageConfiguration.Packages.Package.where{$_.id -eq 'Bonsai'} - if ($bootstrapper) { - $version = $bootstrapper.version - $release = "https://github.com/bonsai-rx/bonsai/releases/download/$version/Bonsai.zip" - } - } - Invoke-WebRequest $release -OutFile "temp.zip" - Move-Item -Path "NuGet.config" "temp.config" -ErrorAction SilentlyContinue - Expand-Archive "temp.zip" -DestinationPath "." -Force - Move-Item -Path "temp.config" "NuGet.config" -Force -ErrorAction SilentlyContinue - Remove-Item -Path "temp.zip" - Remove-Item -Path "Bonsai32.exe" -} -& .\Bonsai.exe --no-editor -Pop-Location \ No newline at end of file diff --git a/assets/root/.github/workflows/build.yml b/assets/root/.github/workflows/build.yml deleted file mode 100644 index 409f5bb..0000000 --- a/assets/root/.github/workflows/build.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Build - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - build: - name: Build Solution - runs-on: windows-latest - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup MSBuild - uses: microsoft/setup-msbuild@v1 - - - name: Setup NuGet - uses: NuGet/setup-nuget@v1.2.0 - - - name: Restore NuGet Packages - run: nuget restore src/Bonsai.Gui.sln - - - name: Build Solution - run: msbuild src/Bonsai.Gui.sln /p:Configuration=Release diff --git a/assets/root/.github/workflows/docs.yml b/assets/root/.github/workflows/docs.yml deleted file mode 100644 index 2ccd282..0000000 --- a/assets/root/.github/workflows/docs.yml +++ /dev/null @@ -1,51 +0,0 @@ -# Builds and publishes the documentation website to gh-pages branch -name: Build docs - -on: - workflow_dispatch: - -jobs: - build: - runs-on: windows-latest - steps: - - name: Checkout - uses: actions/checkout@v4.1.1 - with: - submodules: true - - - name: Setup .NET Core SDK - uses: actions/setup-dotnet@v4.0.0 - with: - dotnet-version: 8.x - - - name: Setup MSBuild - uses: microsoft/setup-msbuild@v2 - - - name: Restore NuGet Packages - run: msbuild -t:restore src/Bonsai.Gui.sln - - - name: Build Solution - run: msbuild src/Bonsai.Gui.sln /p:Configuration=Release - - - name: Setup DocFX - run: dotnet tool restore - - - name: Setup Bonsai - working-directory: .bonsai - run: .\Setup.ps1 - - - name: Build Documentation - working-directory: docs - run: .\build.ps1 - - - name: Checkout gh-pages - uses: actions/checkout@v4.1.1 - with: - ref: gh-pages - path: gh-pages - - name: Publish to github pages - uses: peaceiris/actions-gh-pages@v3.9.3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: docs/_site - force_orphan: true \ No newline at end of file diff --git a/modules/Copy-Files.ipynb b/modules/Copy-Files.ipynb deleted file mode 100644 index 92b68ed..0000000 --- a/modules/Copy-Files.ipynb +++ /dev/null @@ -1,290 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "# Although it might be easier to just copy the entire assets directory, the current format allows selective copying \n", - "# and avoids FileExistsErrors from breaking the entire run\n", - "# might also want to look into refactoring the regex replacement code as a function since its being used quite often\n", - "import os\n", - "import shutil\n", - "import re" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# define folder constants\n", - "current_dir = os.getcwd()\n", - "assets_dir = os.path.join(os.path.dirname(current_dir), \"assets\")\n", - "assets_docs_dir = os.path.join(assets_dir, \"docs\")\n", - "assets_root_dir = os.path.join(assets_dir, \"root\")\n", - "assets_docs_api_dir = os.path.join(assets_docs_dir, \"api\")\n", - "assets_workflows_dir = os.path.join(assets_docs_dir, \"workflows\")\n", - "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", - "docs_dir = os.path.join(root_dir,\"docs\")\n", - "docs_api_dir = os.path.join(docs_dir, \"api\")\n", - "docs_workflows_dir = os.path.join(docs_dir, \"workflows\")\n", - "docs_articles_dir = os.path.join(docs_dir, \"articles\")\n", - "docs_images_dir = os.path.join(docs_dir, \"images\")\n", - "src_dir = os.path.join(root_dir, \"src\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# make folders for docfx\n", - "# try except blocks in case folder already exists\n", - "try:\n", - " os.mkdir(docs_dir)\n", - "except:\n", - " pass\n", - "\n", - "try:\n", - " os.mkdir(docs_articles_dir)\n", - "except:\n", - " pass\n", - "\n", - "try:\n", - " os.mkdir(docs_images_dir)\n", - "except:\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'c:\\\\Users\\\\shawn\\\\.bonsai'" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# copy root/.bonsai folder for making bonsai env\n", - "# asset copied from bonsai-rx/gui 4/22/24\n", - "shutil.copytree(os.path.join(assets_root_dir, \".bonsai\"), os.path.join(root_dir, \".bonsai\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'c:\\\\Users\\\\shawn\\\\.github'" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# copy root/.github folder for github actions\n", - "# asset copied from bonsai-rx/gui 4/22/24\n", - "# to add - automatically search for src sln file\n", - "shutil.copytree(os.path.join(assets_root_dir, \".github\"), os.path.join(root_dir, \".github\"))\n", - "\n", - "new_package_src_sln = input(\"Please enter the location of the package src sln file e.g src/Bonsai.Gui.sln\")\n", - "with open(os.path.join(root_dir, \".github\", \"workflows\", \"build.yml\"), 'r') as file:\n", - " file_content = file.readlines()\n", - " line_position = -1\n", - " for line in file_content:\n", - " line_position += 1\n", - " if \"nuget restore\" in line:\n", - " # line replacement is done in 2 steps due to a bug in re.sub not accepting strings without escape characters\n", - " new_line = re.sub(r\"src/[^/]+\\.sln\", \"text_to_replace\", line)\n", - " new_line = new_line.replace(\"text_to_replace\", new_package_src_sln)\n", - " file_content[line_position] = new_line\n", - " elif \"Configuration=Release\" in line:\n", - " new_line = re.sub(r\"src/[^/]+\\.sln\", \"text_to_replace\", line)\n", - " new_line = new_line.replace(\"text_to_replace\", new_package_src_sln)\n", - " file_content[line_position] = new_line\n", - " else:\n", - " pass\n", - " with open(os.path.join(root_dir, \".github\", \"workflows\", \"build.yml\"), 'w') as new_file:\n", - " new_file.writelines(file_content)\n", - "\n", - "with open(os.path.join(root_dir, \".github\", \"workflows\", \"docs.yml\"), 'r') as file:\n", - " file_content = file.readlines()\n", - " line_position = -1\n", - " for line in file_content:\n", - " line_position += 1\n", - " if \"-t:restore\" in line:\n", - " # line replacement is done in 2 steps due to a bug in re.sub not accepting strings without escape characters\n", - " new_line = re.sub(r\"src/[^/]+\\.sln\", \"text_to_replace\", line)\n", - " new_line = new_line.replace(\"text_to_replace\", new_package_src_sln)\n", - " file_content[line_position] = new_line\n", - " elif \"Configuration=Release\" in line:\n", - " new_line = re.sub(r\"src/[^/]+\\.sln\", \"text_to_replace\", line)\n", - " new_line = new_line.replace(\"text_to_replace\", new_package_src_sln)\n", - " file_content[line_position] = new_line\n", - " else:\n", - " pass\n", - " with open(os.path.join(root_dir, \".github\", \"workflows\", \"docs.yml\"), 'w') as new_file:\n", - " new_file.writelines(file_content)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'c:\\\\Users\\\\shawn\\\\docs'" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# copy docs .gitignore to filter out _site folder\n", - "# asset copied from bonsai-rx/gui 4/22/24\n", - "shutil.copy(os.path.join(assets_docs_dir, \".gitignore\"), docs_dir)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# copy docs favicon and site logo\n", - "# asset copied from bonsai-rx/gui 4/28/24\n", - "shutil.copy(os.path.join(assets_docs_dir, \"favicon.ico\"), docs_dir)\n", - "shutil.copy(os.path.join(assets_docs_dir, \"logo.svg\"), docs_dir)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# copy docs filter.yml to filter out obsolete attributes\n", - "# asset copied from bonsai-rx/gui 4/27/24\n", - "shutil.copy(os.path.join(assets_docs_dir, \"filter.yml\"), docs_dir)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# copy docs/build.ps1 file to export workflow images and modifies script to handle new package\n", - "# asset copied from bonsai-rx/gui 4/22/24\n", - "# to add - automatically search for package location \n", - "\n", - "shutil.copy(os.path.join(assets_docs_dir, \"build.ps1\"), docs_dir)\n", - "\n", - "new_package_src = \"..\\\\\" + input(\"Please enter the location of the package bin e.g src\\Bonsai.Gui.ZedGraph\\bin\\Release\\net472\")\n", - "with open(os.path.join(docs_dir,\"build.ps1\"), 'r') as file:\n", - " file_content = file.readlines()\n", - " for line in file_content:\n", - " # line replacement is done in 2 steps due to a bug in re.sub not accepting strings without escape characters\n", - " new_line = re.sub(r'\"([^\"]*)\"', '\"text_to_replace\"', line)\n", - " new_line = new_line.replace(\"text_to_replace\", new_package_src)\n", - " file_content[0] = new_line\n", - " with open(os.path.join(docs_dir,\"build.ps1\"), 'w') as new_file:\n", - " new_file.writelines(file_content)\n", - " break" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# copy docs/workflows folder\n", - "# asset copied from bonsai-rx/gui 4/23/24\n", - "shutil.copytree(assets_workflows_dir, docs_workflows_dir)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# copy docs/api folder and .gitignore file to filter out automatically generated api yml and manifest file\n", - "# asset copied from bonsai-rx/gui 4/22/24\n", - "shutil.copytree(assets_docs_api_dir, docs_api_dir)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# copy docs/template folder\n", - "# asset copied from bonsai-rx/gui 4/22/24\n", - "\n", - "shutil.copytree(os.path.join(assets_docs_dir, \"template\"), os.path.join(docs_dir, \"template\"))\n", - "\n", - "new_package_github = input(\"Please enter the github link for the new package\")\n", - "with open(os.path.join(docs_dir,\"template\", \"public\", \"main.js\"), 'r') as file:\n", - " file_content = file.readlines()\n", - " line_position = -1\n", - " for line in file_content:\n", - " line_position += 1\n", - " if \"href\" in line:\n", - " # line replacement is done in 2 steps due to a bug in re.sub not accepting strings without escape characters\n", - " new_line = re.sub(r\"'([^']*)'\", \"'text_to_replace'\", line)\n", - " new_line = new_line.replace(\"text_to_replace\", new_package_github)\n", - " file_content[line_position] = new_line\n", - " with open(os.path.join(docs_dir,\"template\", \"public\", \"main.js\"), 'w') as new_file:\n", - " new_file.writelines(file_content)\n", - " break\n", - " else:\n", - " pass" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "base", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.7" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/modules/Export-Individual-Node-Workflows.ipynb b/modules/Export-Individual-Node-Workflows.ipynb deleted file mode 100644 index 3fcd09c..0000000 --- a/modules/Export-Individual-Node-Workflows.ipynb +++ /dev/null @@ -1,151 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "# import libraries\n", - "import os" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [], - "source": [ - "# function to extract operator names, location, and namespace from a given source folder\n", - "def extract_operator_names_location(directory):\n", - " file_list = []\n", - " operator_list = []\n", - " for root, dirs, files in os.walk(directory):\n", - " for file in files:\n", - " if file.endswith(\"cs\"):\n", - " # skips .cs files in debug and release folder that arent Bonsai operators\n", - " # some operators (for instance NumpyHelper and TimeSeriesOxyPlotBase) do not show up in API docs but nsure why\n", - " if \"Release\" not in root:\n", - " if \"Debug\" not in root:\n", - " if \"Properties\" not in root:\n", - " operator_property_list = []\n", - " file_list.append(os.path.join(root, file))\n", - " operator_list.append(file[:-3])\n", - " operator_dictionary = {operator_list[i]: [file_list[i]] for i in range(len(file_list))}\n", - " return operator_dictionary" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": {}, - "outputs": [], - "source": [ - "# define folder constants\n", - "current_dir = os.getcwd()\n", - "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", - "docs_dir = os.path.join(root_dir,\"docs\")\n", - "src_dir = os.path.join(root_dir, \"src\")" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [], - "source": [ - "# extract operator dictionary containing operator name as a key and a tuple value with location and namespace)\n", - "operator_dictionary = extract_operator_names_location(src_dir)" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ChannelTriggers ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ChannelTriggers.cs', 'Bonsai.PulsePal', ['ChannelTriggers']]\n", - "CombinatorTypeConverter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CombinatorTypeConverter.cs', 'Bonsai.PulsePal', []]\n", - "ConfigureChannelParameter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureChannelParameter.cs', 'Bonsai.PulsePal', ['DeviceName', 'Parameter']]\n", - "ConfigureOutputChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureOutputChannel.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", - "ConfigureTriggerChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureTriggerChannel.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", - "CreatePulsePal ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CreatePulsePal.cs', 'Bonsai.PulsePal', ['DeviceName', 'PortName', 'OutputChannels', 'TriggerChannels']]\n", - "CustomPulseTrain ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomPulseTrain.cs', 'Bonsai.PulsePal', []]\n", - "CustomTrainId ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomTrainId.cs', 'Bonsai.PulsePal', ['CustomTrainId']]\n", - "CustomTrainTarget ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomTrainTarget.cs', 'Bonsai.PulsePal', ['CustomTrainTarget']]\n", - "DeviceNameConverter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\DeviceNameConverter.cs', 'Bonsai.PulsePal', []]\n", - "OutputChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\OutputChannel.cs', 'Bonsai.PulsePal', ['OutputChannel']]\n", - "ParameterCode ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ParameterCode.cs', 'Bonsai.PulsePal', []]\n", - "PolymorphicCombinator ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PolymorphicCombinator.cs', 'Bonsai.PulsePal', ['descr)']]\n", - "PulseOnset ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulseOnset.cs', 'Bonsai.PulsePal', ['Time', 'Voltage']]\n", - "PulsePalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalConfiguration.cs', 'Bonsai.PulsePal', ['PortName']]\n", - "PulsePalDevice ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalDevice.cs', 'Bonsai.PulsePal', ['FirmwareVersion', 'IsOpen', 'pulsePal)']]\n", - "PulsePalDisposable ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalDisposable.cs', 'Bonsai.PulsePal', ['pulsePal,', 'PulsePal', 'IsDisposed']]\n", - "PulsePalManager ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalManager.cs', 'Bonsai.PulsePal', []]\n", - "SendCustomPulseTrain ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SendCustomPulseTrain.cs', 'Bonsai.PulsePal', ['DeviceName', 'CustomTrainIdentity']]\n", - "SendCustomWaveform ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SendCustomWaveform.cs', 'Bonsai.PulsePal', ['DeviceName', 'CustomTrainIdentity', 'SamplingPeriod']]\n", - "SetFixedVoltage ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SetFixedVoltage.cs', 'Bonsai.PulsePal', ['DeviceName', 'Channel', 'Voltage']]\n", - "TriggerChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerChannel.cs', 'Bonsai.PulsePal', ['TriggerChannel']]\n", - "TriggerMode ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerMode.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", - "TriggerOutputChannels ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerOutputChannels.cs', 'Bonsai.PulsePal', ['DeviceName', 'Channels']]\n", - "UpdateDisplay ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\UpdateDisplay.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", - "BiphasicConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\BiphasicConfiguration.cs', 'Bonsai.PulsePal', ['Biphasic']]\n", - "BurstDurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\BurstDurationConfiguration.cs', 'Bonsai.PulsePal', ['BurstDuration']]\n", - "ChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\ChannelParameterConfiguration.cs', 'Bonsai.PulsePal', []]\n", - "ContinuousLoopConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\ContinuousLoopConfiguration.cs', 'Bonsai.PulsePal', ['ContinuousLoop']]\n", - "CustomTrainIdentityConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainIdentityConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainIdentity']]\n", - "CustomTrainLoopConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainLoopConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainLoop']]\n", - "CustomTrainTargetConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainTargetConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainTarget']]\n", - "InterBurstIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterBurstIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterBurstInterval']]\n", - "InterPhaseIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterPhaseIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterPhaseInterval']]\n", - "InterPulseIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterPulseIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterPulseInterval']]\n", - "OutputChannelConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelConfiguration.cs', 'Bonsai.PulsePal', ['Biphasic', 'Phase1Voltage', 'Phase2Voltage', 'RestingVoltage', 'PulseTrainDelay', 'Phase1Duration', 'InterPhaseInterval', 'Phase2Duration', 'InterPulseInterval', 'BurstDuration', 'InterBurstInterval', 'PulseTrainDuration', 'CustomTrainIdentity', 'CustomTrainTarget', 'CustomTrainLoop', 'TriggerOnChannel1', 'TriggerOnChannel2', 'ContinuousLoop']]\n", - "OutputChannelConfigurationCollection ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelConfigurationCollection.cs', 'Bonsai.PulsePal', []]\n", - "OutputChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelParameterConfiguration.cs', 'Bonsai.PulsePal', ['Channel']]\n", - "Phase1DurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase1DurationConfiguration.cs', 'Bonsai.PulsePal', ['Phase1Duration']]\n", - "Phase1VoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase1VoltageConfiguration.cs', 'Bonsai.PulsePal', ['Phase1Voltage']]\n", - "Phase2DurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase2DurationConfiguration.cs', 'Bonsai.PulsePal', ['Phase2Duration']]\n", - "Phase2VoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase2VoltageConfiguration.cs', 'Bonsai.PulsePal', ['Phase2Voltage']]\n", - "PulseTrainDelayConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\PulseTrainDelayConfiguration.cs', 'Bonsai.PulsePal', ['PulseTrainDelay']]\n", - "PulseTrainDurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\PulseTrainDurationConfiguration.cs', 'Bonsai.PulsePal', ['PulseTrainDuration']]\n", - "RestingVoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\RestingVoltageConfiguration.cs', 'Bonsai.PulsePal', ['RestingVoltage']]\n", - "TriggerChannelConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelConfiguration.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", - "TriggerChannelConfigurationCollection ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelConfigurationCollection.cs', 'Bonsai.PulsePal', []]\n", - "TriggerChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelParameterConfiguration.cs', 'Bonsai.PulsePal', ['Channel']]\n", - "TriggerModeConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerModeConfiguration.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", - "TriggerOnChannel1Configuration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerOnChannel1Configuration.cs', 'Bonsai.PulsePal', ['TriggerOnChannel1']]\n", - "TriggerOnChannel2Configuration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerOnChannel2Configuration.cs', 'Bonsai.PulsePal', ['TriggerOnChannel2']]\n" - ] - } - ], - "source": [ - "for key, value in operator_dictionary.items():\n", - " print(key, value)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "base", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.7" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/modules/export-xref.ipynb b/modules/export-xref.ipynb deleted file mode 100644 index e925b94..0000000 --- a/modules/export-xref.ipynb +++ /dev/null @@ -1,195 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "# import libraries\n", - "import os" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [], - "source": [ - "# function to extract operator names, location, and namespace from a given source folder\n", - "def extract_operator_names_location_namespace(directory):\n", - " file_list = []\n", - " operator_list = []\n", - " namespace_list = []\n", - " property_list = []\n", - " for root, dirs, files in os.walk(directory):\n", - " for file in files:\n", - " if file.endswith(\"cs\"):\n", - " # skips .cs files in debug and release folder that arent Bonsai operators\n", - " # some operators (for instance NumpyHelper and TimeSeriesOxyPlotBase) do not show up in API docs but nsure why\n", - " if \"Release\" not in root:\n", - " if \"Debug\" not in root:\n", - " if \"Properties\" not in root:\n", - " operator_property_list = []\n", - " file_list.append(os.path.join(root, file))\n", - " operator_list.append(file[:-3])\n", - " with open(os.path.join(root, file), 'r') as cs_file:\n", - " # Read the file line by line\n", - " for line in cs_file:\n", - " # Check if the line contains a namespace declaration\n", - " if \"namespace\" in line:\n", - " # Extract the namespace from the line, strips bracket if any\n", - " namespace = line.strip().split(\" \")[1]\n", - " namespace_list.append(namespace)\n", - " # Stop searching after finding the namespace declaration (add it back in if property extraction is not needed)\n", - " # break \n", - " # this \"hackety\" approach relies on finding all public declarations and omitting certain declarations\n", - " # the alternative approach of finding positive declaration fails because some properties are declared with package specific components \n", - " # example of previous approach: elif line.strip().startswith((\"public string\",\"public TypeMapping\", \"public double\", \"public StateComponent\")):\n", - " \n", - " # this method was tested on machine learning docs \n", - " elif line.strip().startswith(\"public\"):\n", - " if \"class\" in line:\n", - " pass\n", - " elif \"()\" in line:\n", - " pass\n", - " elif \"Process\" in line:\n", - " pass\n", - " elif \"override\" in line:\n", - " pass\n", - " elif \"Event\" in line:\n", - " pass\n", - " elif \"static\" in line:\n", - " pass\n", - " elif \"readonly\" in line:\n", - " pass\n", - " elif \"PyObject\" in line:\n", - " pass\n", - " elif \"(string\" in line:\n", - " pass\n", - " elif \"(double\" in line:\n", - " pass\n", - " elif \"void\" in line:\n", - " pass\n", - " else:\n", - " property = line.strip().split(\" \")[2]\n", - " operator_property_list.append(property)\n", - " property_list.append(operator_property_list) \n", - " operator_dictionary = {operator_list[i]: [file_list[i],namespace_list[i],property_list[i]] for i in range(len(file_list))}\n", - " return operator_dictionary" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": {}, - "outputs": [], - "source": [ - "# define folder constants\n", - "current_dir = os.getcwd()\n", - "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", - "docs_dir = os.path.join(root_dir,\"docs\")\n", - "src_dir = os.path.join(root_dir, \"src\")" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [], - "source": [ - "# extract operator dictionary containing operator name as a key and a tuple value with location and namespace)\n", - "operator_dictionary = extract_operator_names_location_namespace(src_dir)" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ChannelTriggers ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ChannelTriggers.cs', 'Bonsai.PulsePal', ['ChannelTriggers']]\n", - "CombinatorTypeConverter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CombinatorTypeConverter.cs', 'Bonsai.PulsePal', []]\n", - "ConfigureChannelParameter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureChannelParameter.cs', 'Bonsai.PulsePal', ['DeviceName', 'Parameter']]\n", - "ConfigureOutputChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureOutputChannel.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", - "ConfigureTriggerChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ConfigureTriggerChannel.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", - "CreatePulsePal ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CreatePulsePal.cs', 'Bonsai.PulsePal', ['DeviceName', 'PortName', 'OutputChannels', 'TriggerChannels']]\n", - "CustomPulseTrain ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomPulseTrain.cs', 'Bonsai.PulsePal', []]\n", - "CustomTrainId ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomTrainId.cs', 'Bonsai.PulsePal', ['CustomTrainId']]\n", - "CustomTrainTarget ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\CustomTrainTarget.cs', 'Bonsai.PulsePal', ['CustomTrainTarget']]\n", - "DeviceNameConverter ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\DeviceNameConverter.cs', 'Bonsai.PulsePal', []]\n", - "OutputChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\OutputChannel.cs', 'Bonsai.PulsePal', ['OutputChannel']]\n", - "ParameterCode ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\ParameterCode.cs', 'Bonsai.PulsePal', []]\n", - "PolymorphicCombinator ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PolymorphicCombinator.cs', 'Bonsai.PulsePal', ['descr)']]\n", - "PulseOnset ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulseOnset.cs', 'Bonsai.PulsePal', ['Time', 'Voltage']]\n", - "PulsePalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalConfiguration.cs', 'Bonsai.PulsePal', ['PortName']]\n", - "PulsePalDevice ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalDevice.cs', 'Bonsai.PulsePal', ['FirmwareVersion', 'IsOpen', 'pulsePal)']]\n", - "PulsePalDisposable ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalDisposable.cs', 'Bonsai.PulsePal', ['pulsePal,', 'PulsePal', 'IsDisposed']]\n", - "PulsePalManager ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\PulsePalManager.cs', 'Bonsai.PulsePal', []]\n", - "SendCustomPulseTrain ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SendCustomPulseTrain.cs', 'Bonsai.PulsePal', ['DeviceName', 'CustomTrainIdentity']]\n", - "SendCustomWaveform ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SendCustomWaveform.cs', 'Bonsai.PulsePal', ['DeviceName', 'CustomTrainIdentity', 'SamplingPeriod']]\n", - "SetFixedVoltage ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\SetFixedVoltage.cs', 'Bonsai.PulsePal', ['DeviceName', 'Channel', 'Voltage']]\n", - "TriggerChannel ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerChannel.cs', 'Bonsai.PulsePal', ['TriggerChannel']]\n", - "TriggerMode ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerMode.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", - "TriggerOutputChannels ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\TriggerOutputChannels.cs', 'Bonsai.PulsePal', ['DeviceName', 'Channels']]\n", - "UpdateDisplay ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\UpdateDisplay.cs', 'Bonsai.PulsePal', ['DeviceName']]\n", - "BiphasicConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\BiphasicConfiguration.cs', 'Bonsai.PulsePal', ['Biphasic']]\n", - "BurstDurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\BurstDurationConfiguration.cs', 'Bonsai.PulsePal', ['BurstDuration']]\n", - "ChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\ChannelParameterConfiguration.cs', 'Bonsai.PulsePal', []]\n", - "ContinuousLoopConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\ContinuousLoopConfiguration.cs', 'Bonsai.PulsePal', ['ContinuousLoop']]\n", - "CustomTrainIdentityConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainIdentityConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainIdentity']]\n", - "CustomTrainLoopConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainLoopConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainLoop']]\n", - "CustomTrainTargetConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\CustomTrainTargetConfiguration.cs', 'Bonsai.PulsePal', ['CustomTrainTarget']]\n", - "InterBurstIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterBurstIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterBurstInterval']]\n", - "InterPhaseIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterPhaseIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterPhaseInterval']]\n", - "InterPulseIntervalConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\InterPulseIntervalConfiguration.cs', 'Bonsai.PulsePal', ['InterPulseInterval']]\n", - "OutputChannelConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelConfiguration.cs', 'Bonsai.PulsePal', ['Biphasic', 'Phase1Voltage', 'Phase2Voltage', 'RestingVoltage', 'PulseTrainDelay', 'Phase1Duration', 'InterPhaseInterval', 'Phase2Duration', 'InterPulseInterval', 'BurstDuration', 'InterBurstInterval', 'PulseTrainDuration', 'CustomTrainIdentity', 'CustomTrainTarget', 'CustomTrainLoop', 'TriggerOnChannel1', 'TriggerOnChannel2', 'ContinuousLoop']]\n", - "OutputChannelConfigurationCollection ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelConfigurationCollection.cs', 'Bonsai.PulsePal', []]\n", - "OutputChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\OutputChannelParameterConfiguration.cs', 'Bonsai.PulsePal', ['Channel']]\n", - "Phase1DurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase1DurationConfiguration.cs', 'Bonsai.PulsePal', ['Phase1Duration']]\n", - "Phase1VoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase1VoltageConfiguration.cs', 'Bonsai.PulsePal', ['Phase1Voltage']]\n", - "Phase2DurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase2DurationConfiguration.cs', 'Bonsai.PulsePal', ['Phase2Duration']]\n", - "Phase2VoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\Phase2VoltageConfiguration.cs', 'Bonsai.PulsePal', ['Phase2Voltage']]\n", - "PulseTrainDelayConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\PulseTrainDelayConfiguration.cs', 'Bonsai.PulsePal', ['PulseTrainDelay']]\n", - "PulseTrainDurationConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\PulseTrainDurationConfiguration.cs', 'Bonsai.PulsePal', ['PulseTrainDuration']]\n", - "RestingVoltageConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\RestingVoltageConfiguration.cs', 'Bonsai.PulsePal', ['RestingVoltage']]\n", - "TriggerChannelConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelConfiguration.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", - "TriggerChannelConfigurationCollection ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelConfigurationCollection.cs', 'Bonsai.PulsePal', []]\n", - "TriggerChannelParameterConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerChannelParameterConfiguration.cs', 'Bonsai.PulsePal', ['Channel']]\n", - "TriggerModeConfiguration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerModeConfiguration.cs', 'Bonsai.PulsePal', ['TriggerMode']]\n", - "TriggerOnChannel1Configuration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerOnChannel1Configuration.cs', 'Bonsai.PulsePal', ['TriggerOnChannel1']]\n", - "TriggerOnChannel2Configuration ['c:\\\\Users\\\\shawn\\\\Desktop\\\\pulsepal_docs_rev\\\\src\\\\Bonsai.PulsePal\\\\Configuration\\\\TriggerOnChannel2Configuration.cs', 'Bonsai.PulsePal', ['TriggerOnChannel2']]\n" - ] - } - ], - "source": [ - "for key, value in operator_dictionary.items():\n", - " print(key, value)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "base", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.7" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From aacdb5eb2026155e77a572191b223af5774efdaf Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 16 Sep 2024 16:01:28 -0700 Subject: [PATCH 29/35] Convert script from .ipynb to .py, update README --- README.md | 6 +- modules/Configure-Json.ipynb | 230 ----------------------------------- modules/Configure-Json.py | 92 ++++++++++++++ 3 files changed, 96 insertions(+), 232 deletions(-) delete mode 100644 modules/Configure-Json.ipynb create mode 100644 modules/Configure-Json.py diff --git a/README.md b/README.md index 26e534e..818fa2b 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,10 @@ Exporting SVG images for all example workflows can be automated by placing all ` ## Configure Json -This script modifies `docfx.json` to reproduce the customisation options that are most frequently applied for Bonsai package documentation websites. Call the script with the following command and enter details when prompted: +This script modifies `docfx.json` to reproduce the customisation options that are most frequently applied for Bonsai package documentation websites. This script assumes a (python)[https://www.python.org/downloads/] installation. Call the script with the following command and enter details when prompted: ```ps1 python .\modules\Configure-Json.py -``` \ No newline at end of file +``` + +Verify the modified `docfx.json` for accuracy, especially for external developers, since the script was made for internal development. \ No newline at end of file diff --git a/modules/Configure-Json.ipynb b/modules/Configure-Json.ipynb deleted file mode 100644 index fc46958..0000000 --- a/modules/Configure-Json.ipynb +++ /dev/null @@ -1,230 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# code based on comparing bonsai.gui docfx.json file to a fresh docfx.json (updated 4/27/24)\n", - "# might be easier to just copy the docfx.json file but it might change when docfx is updated.\n", - "import json\n", - "import os" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# define folder constants\n", - "current_dir = os.getcwd()\n", - "root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))\n", - "docs_dir = os.path.join(root_dir,\"docs\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# load json file\n", - "try:\n", - " with open(os.path.join(docs_dir, \"docfx.json\"), 'r') as file:\n", - " data = json.load(file)\n", - "except FileNotFoundError:\n", - " print(\"docfx.json not file, run docfx first to create docfx.json file\")" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "# prompt for github website\n", - "github_link = input(\"Please enter the github website\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# prompt for package name\n", - "package_name = input(\"Please enter the package name for the website - for instance ML for Bonsai.ML\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# adds filter .yml to metadata build\n", - "# the structure in the attributes is a bit weird, its a dictionary in a list, so the index [0] is just calling up that dictionary\n", - "data[\"metadata\"][0][\"filter\"] = \"filter.yml\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# adds files and folders to be excluded from site building\n", - "if \"filter.yml\" in data[\"build\"][\"content\"][0][\"exclude\"]:\n", - " pass\n", - "else:\n", - " data[\"build\"][\"content\"][0][\"exclude\"].extend([\"filter.yml\"])\n", - " \n", - "if \"bonsai/**\" in data[\"build\"][\"content\"][0][\"exclude\"]:\n", - " pass\n", - "else:\n", - " data[\"build\"][\"content\"][0][\"exclude\"].extend([\"bonsai/**\"])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# adds site resources\n", - "if \"workflows/**\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", - " pass\n", - "else: \n", - " data[\"build\"][\"resource\"][0][\"files\"].extend([\"workflows/**\"])\n", - " \n", - "if \"logo.svg\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", - " pass\n", - "else: \n", - " data[\"build\"][\"resource\"][0][\"files\"].extend([\"logo.svg\"])\n", - "\n", - "if \"favicon.ico\" in data[\"build\"][\"resource\"][0][\"files\"]:\n", - " pass\n", - "else: \n", - " data[\"build\"][\"resource\"][0][\"files\"].extend([\"favicon.ico\"])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# adds overwrite section\n", - "data[\"build\"][\"overwrite\"] = [{\"files\":[\"apidoc/**.md\"], \n", - " \"exclude\": [\"obj/**\", \"_site/**\"]}]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# adds bonsai templates \n", - "if \"bonsai/template\" in data[\"build\"][\"template\"]:\n", - " pass\n", - "else:\n", - " data[\"build\"][\"template\"].extend([\"bonsai/template\"])\n", - " \n", - "if \"template\" in data[\"build\"][\"template\"]:\n", - " pass\n", - "else:\n", - " data[\"build\"][\"template\"].extend([\"template\"])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# adds app name and website\n", - "data[\"build\"][\"globalMetadata\"][\"_appName\"] = \"Bonsai - \" + package_name\n", - "data[\"build\"][\"globalMetadata\"][\"_appTitle\"] = \"Bonsai.\" + package_name" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# adds site footer\n", - "data[\"build\"][\"globalMetadata\"][\"_appFooter\"] = \"© 2024 Bonsai Foundation CIC and Contributors. Made with docfx\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# adds git contribute section\n", - "data[\"build\"][\"globalMetadata\"][\"_gitContribute\"] = {\"repo\": github_link, \n", - " \"branch\": \"main\", \n", - " \"apiSpecFolder\": \"apidoc\"}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# adds markdig extensions\n", - "data[\"build\"][\"markdownEngineProperties\"] = {\"markdigExtensions\": [\"attributes\",\n", - " \"customcontainers\"]}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# adds xref \n", - "data[\"build\"][\"xref\"] = [\"https://bonsai-rx.org/docs/xrefmap.yml\",\n", - " \"https://horizongir.github.io/reactive/xrefmap.yml\"]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# write json file\n", - "with open(os.path.join(docs_dir, \"docfx.json\"), 'w') as file:\n", - " json.dump(data, file, indent=2)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "base", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.7" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/modules/Configure-Json.py b/modules/Configure-Json.py new file mode 100644 index 0000000..128f390 --- /dev/null +++ b/modules/Configure-Json.py @@ -0,0 +1,92 @@ +# code based on comparing bonsai.gui docfx.json file to a fresh docfx.json (updated 4/27/24) +# might be easier to just copy the docfx.json file but it might change when docfx is updated. +import json +import os + +# define folder constants +current_dir = os.getcwd() +root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir))) +docs_dir = os.path.join(root_dir,"docs") + +# load json file +try: + with open(os.path.join(docs_dir, "docfx.json"), 'r') as file: + data = json.load(file) +except FileNotFoundError: + print("docfx.json not file, run docfx first to create docfx.json file") + +# prompt for github website +github_link = input("Please enter the github website") + +# prompt for package name +package_name = input("Please enter the package name for the website - for instance ML for Bonsai.ML") + +# adds filter .yml to metadata build +# the structure in the attributes is a bit weird, its a dictionary in a list, so the index [0] is just calling up that dictionary +data["metadata"][0]["filter"] = "filter.yml" + +# adds files and folders to be excluded from site building +if "filter.yml" in data["build"]["content"][0]["exclude"]: + pass +else: + data["build"]["content"][0]["exclude"].extend(["filter.yml"]) + +if "bonsai/**" in data["build"]["content"][0]["exclude"]: + pass +else: + data["build"]["content"][0]["exclude"].extend(["bonsai/**"]) + +# adds site resources +if "workflows/**" in data["build"]["resource"][0]["files"]: + pass +else: + data["build"]["resource"][0]["files"].extend(["workflows/**"]) + +if "logo.svg" in data["build"]["resource"][0]["files"]: + pass +else: + data["build"]["resource"][0]["files"].extend(["logo.svg"]) + +if "favicon.ico" in data["build"]["resource"][0]["files"]: + pass +else: + data["build"]["resource"][0]["files"].extend(["favicon.ico"]) + +# adds overwrite section +data["build"]["overwrite"] = [{"files":["apidoc/**.md"], + "exclude": ["obj/**", "_site/**"]}] + +# adds bonsai templates +if "bonsai/template" in data["build"]["template"]: + pass +else: + data["build"]["template"].extend(["bonsai/template"]) + +if "template" in data["build"]["template"]: + pass +else: + data["build"]["template"].extend(["template"]) + +# adds app name and website +data["build"]["globalMetadata"]["_appName"] = "Bonsai - " + package_name +data["build"]["globalMetadata"]["_appTitle"] = "Bonsai." + package_name + +# adds site footer +data["build"]["globalMetadata"]["_appFooter"] = "© 2024 Bonsai Foundation CIC and Contributors. Made with docfx" + +# adds git contribute section +data["build"]["globalMetadata"]["_gitContribute"] = {"repo": github_link, + "branch": "main", + "apiSpecFolder": "apidoc"} + +# adds markdig extensions +data["build"]["markdownEngineProperties"] = {"markdigExtensions": ["attributes", + "customcontainers"]} + +# adds xref +data["build"]["xref"] = ["https://bonsai-rx.org/docs/xrefmap.yml", + "https://horizongir.github.io/reactive/xrefmap.yml"] + +# write json file +with open(os.path.join(docs_dir, "docfx.json"), 'w') as file: + json.dump(data, file, indent=2) \ No newline at end of file From 0927f525564f206bb5e66f66f355b23c510aa46d Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 16 Sep 2024 16:06:21 -0700 Subject: [PATCH 30/35] Remove package name attribute --- modules/Configure-Json.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/modules/Configure-Json.py b/modules/Configure-Json.py index 128f390..01bcc93 100644 --- a/modules/Configure-Json.py +++ b/modules/Configure-Json.py @@ -18,9 +18,6 @@ # prompt for github website github_link = input("Please enter the github website") -# prompt for package name -package_name = input("Please enter the package name for the website - for instance ML for Bonsai.ML") - # adds filter .yml to metadata build # the structure in the attributes is a bit weird, its a dictionary in a list, so the index [0] is just calling up that dictionary data["metadata"][0]["filter"] = "filter.yml" @@ -67,10 +64,6 @@ else: data["build"]["template"].extend(["template"]) -# adds app name and website -data["build"]["globalMetadata"]["_appName"] = "Bonsai - " + package_name -data["build"]["globalMetadata"]["_appTitle"] = "Bonsai." + package_name - # adds site footer data["build"]["globalMetadata"]["_appFooter"] = "© 2024 Bonsai Foundation CIC and Contributors. Made with docfx" From 2cb062d8649907ecea6aad98b2a5f0ee971d0901 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 16 Sep 2024 16:09:23 -0700 Subject: [PATCH 31/35] Remove reactive xrefmap --- modules/Configure-Json.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/Configure-Json.py b/modules/Configure-Json.py index 01bcc93..8c5b24f 100644 --- a/modules/Configure-Json.py +++ b/modules/Configure-Json.py @@ -77,8 +77,7 @@ "customcontainers"]} # adds xref -data["build"]["xref"] = ["https://bonsai-rx.org/docs/xrefmap.yml", - "https://horizongir.github.io/reactive/xrefmap.yml"] +data["build"]["xref"] = ["https://bonsai-rx.org/docs/xrefmap.yml"] # write json file with open(os.path.join(docs_dir, "docfx.json"), 'w') as file: From fcd5beb2e88ec3fa45dbf09911edb0888a13dbd4 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 16 Sep 2024 17:10:25 -0700 Subject: [PATCH 32/35] Update docfx.json check error --- modules/Configure-Json.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/Configure-Json.py b/modules/Configure-Json.py index 8c5b24f..2b1e36a 100644 --- a/modules/Configure-Json.py +++ b/modules/Configure-Json.py @@ -13,10 +13,12 @@ with open(os.path.join(docs_dir, "docfx.json"), 'r') as file: data = json.load(file) except FileNotFoundError: - print("docfx.json not file, run docfx first to create docfx.json file") + exit_string = "expected docfx.json at " + (os.path.join(docs_dir, "docfx.json") + ", run docfx first to create docfx.json file") + print(exit_string) + os.exit(1) # prompt for github website -github_link = input("Please enter the github website") +github_link = input("Please enter the github website: ") # adds filter .yml to metadata build # the structure in the attributes is a bit weird, its a dictionary in a list, so the index [0] is just calling up that dictionary From cf42da9db04ca9b1a20416793678166eeee89aa8 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Tue, 17 Sep 2024 00:32:43 -0700 Subject: [PATCH 33/35] Refactor and add checks --- modules/Configure-Json.py | 59 ++++++++------------------------------- 1 file changed, 11 insertions(+), 48 deletions(-) diff --git a/modules/Configure-Json.py b/modules/Configure-Json.py index 2b1e36a..4de06f8 100644 --- a/modules/Configure-Json.py +++ b/modules/Configure-Json.py @@ -1,12 +1,9 @@ -# code based on comparing bonsai.gui docfx.json file to a fresh docfx.json (updated 4/27/24) -# might be easier to just copy the docfx.json file but it might change when docfx is updated. import json import os # define folder constants current_dir = os.getcwd() -root_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir))) -docs_dir = os.path.join(root_dir,"docs") +docs_dir = os.path.dirname(os.path.dirname(current_dir)) # load json file try: @@ -17,66 +14,32 @@ print(exit_string) os.exit(1) -# prompt for github website -github_link = input("Please enter the github website: ") - # adds filter .yml to metadata build -# the structure in the attributes is a bit weird, its a dictionary in a list, so the index [0] is just calling up that dictionary data["metadata"][0]["filter"] = "filter.yml" -# adds files and folders to be excluded from site building -if "filter.yml" in data["build"]["content"][0]["exclude"]: - pass -else: - data["build"]["content"][0]["exclude"].extend(["filter.yml"]) +# adds filter.yml to be excluded from site building +if "filter.yml" not in data["build"]["content"][0]["exclude"]: + data["build"]["content"][0]["exclude"].append("filter.yml") -if "bonsai/**" in data["build"]["content"][0]["exclude"]: - pass -else: - data["build"]["content"][0]["exclude"].extend(["bonsai/**"]) - # adds site resources -if "workflows/**" in data["build"]["resource"][0]["files"]: - pass -else: - data["build"]["resource"][0]["files"].extend(["workflows/**"]) - -if "logo.svg" in data["build"]["resource"][0]["files"]: - pass -else: - data["build"]["resource"][0]["files"].extend(["logo.svg"]) - -if "favicon.ico" in data["build"]["resource"][0]["files"]: - pass -else: - data["build"]["resource"][0]["files"].extend(["favicon.ico"]) +data["build"]["resource"][0]["files"].extend( + [file for file in ["workflows/**", "logo.svg", "favicon.ico"] if file not in data["build"]["resource"][0]["files"]] +) # adds overwrite section data["build"]["overwrite"] = [{"files":["apidoc/**.md"], "exclude": ["obj/**", "_site/**"]}] # adds bonsai templates -if "bonsai/template" in data["build"]["template"]: - pass -else: - data["build"]["template"].extend(["bonsai/template"]) - -if "template" in data["build"]["template"]: - pass -else: - data["build"]["template"].extend(["template"]) +data["build"]["template"].extend( + [item for item in ["bonsai/template", "template"] if item not in data["build"]["template"]] +) # adds site footer data["build"]["globalMetadata"]["_appFooter"] = "© 2024 Bonsai Foundation CIC and Contributors. Made with docfx" -# adds git contribute section -data["build"]["globalMetadata"]["_gitContribute"] = {"repo": github_link, - "branch": "main", - "apiSpecFolder": "apidoc"} - # adds markdig extensions -data["build"]["markdownEngineProperties"] = {"markdigExtensions": ["attributes", - "customcontainers"]} +data["build"]["markdownEngineProperties"] = {"markdigExtensions": ["attributes", "customcontainers"]} # adds xref data["build"]["xref"] = ["https://bonsai-rx.org/docs/xrefmap.yml"] From aa59e64c249ce57a3c58e9b5a70fd30f03f1beb3 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Tue, 17 Sep 2024 12:05:03 -0700 Subject: [PATCH 34/35] Refactor code, add checks, trim options --- README.md | 6 +++--- modules/Configure-Json.py | 33 +++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 818fa2b..8245565 100644 --- a/README.md +++ b/README.md @@ -53,10 +53,10 @@ Exporting SVG images for all example workflows can be automated by placing all ` ## Configure Json -This script modifies `docfx.json` to reproduce the customisation options that are most frequently applied for Bonsai package documentation websites. This script assumes a (python)[https://www.python.org/downloads/] installation. Call the script with the following command and enter details when prompted: +This script modifies `docfx.json` to reproduce the customisation options that are most frequently applied for Bonsai package documentation websites. This script assumes a (python)[https://www.python.org/downloads/] installation. Use the script on a newly created `docfx.json` file: ```ps1 -python .\modules\Configure-Json.py +python Configure-Json.py ``` -Verify the modified `docfx.json` for accuracy, especially for external developers, since the script was made for internal development. \ No newline at end of file +Verify the modified `docfx.json` and amend as necessary (especially for external Bonsai developers). \ No newline at end of file diff --git a/modules/Configure-Json.py b/modules/Configure-Json.py index 4de06f8..5223291 100644 --- a/modules/Configure-Json.py +++ b/modules/Configure-Json.py @@ -1,11 +1,11 @@ import json import os -# define folder constants +# Define folder constants current_dir = os.getcwd() docs_dir = os.path.dirname(os.path.dirname(current_dir)) -# load json file +# Load docfx.json file try: with open(os.path.join(docs_dir, "docfx.json"), 'r') as file: data = json.load(file) @@ -14,36 +14,41 @@ print(exit_string) os.exit(1) -# adds filter .yml to metadata build +# Add filtering option to avoid documenting operators that are no longer supported +# but included in the package for backwards compatibility. Can also be used +# to hide private classes that are not supposed to be shown to the end user. +# Make sure a filter.yml is created in docs/filter.yml data["metadata"][0]["filter"] = "filter.yml" -# adds filter.yml to be excluded from site building +# Exclude filter.yml from site building if "filter.yml" not in data["build"]["content"][0]["exclude"]: data["build"]["content"][0]["exclude"].append("filter.yml") -# adds site resources +# Imports site resources data["build"]["resource"][0]["files"].extend( [file for file in ["workflows/**", "logo.svg", "favicon.ico"] if file not in data["build"]["resource"][0]["files"]] ) -# adds overwrite section -data["build"]["overwrite"] = [{"files":["apidoc/**.md"], - "exclude": ["obj/**", "_site/**"]}] +# Use docfx overwrite feature to include individual operator articles in API documentation +data["build"]["overwrite"] = [{"files": ["apidoc/**.md"], "exclude": ["obj/**", "_site/**"]}] -# adds bonsai templates +# Adds custom docfx templates for workflow containers data["build"]["template"].extend( [item for item in ["bonsai/template", "template"] if item not in data["build"]["template"]] ) -# adds site footer +# Adds site footer data["build"]["globalMetadata"]["_appFooter"] = "© 2024 Bonsai Foundation CIC and Contributors. Made with docfx" -# adds markdig extensions +# Enable markdig extensions for additional markdown functionality data["build"]["markdownEngineProperties"] = {"markdigExtensions": ["attributes", "customcontainers"]} -# adds xref +# Enable crossreferencing for Bonsai operator Library data["build"]["xref"] = ["https://bonsai-rx.org/docs/xrefmap.yml"] -# write json file +# Write docfx.json file with open(os.path.join(docs_dir, "docfx.json"), 'w') as file: - json.dump(data, file, indent=2) \ No newline at end of file + json.dump(data, file, indent=2) + +# Script termination message +print("docfx.json modified") \ No newline at end of file From c728af1a9327ee923eb577f6dd0271ddcfc3b200 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Wed, 18 Sep 2024 13:23:25 -0700 Subject: [PATCH 35/35] Exclude apidoc from build to avoid DuplicateUid --- modules/Configure-Json.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/Configure-Json.py b/modules/Configure-Json.py index 5223291..fec1b03 100644 --- a/modules/Configure-Json.py +++ b/modules/Configure-Json.py @@ -20,9 +20,12 @@ # Make sure a filter.yml is created in docs/filter.yml data["metadata"][0]["filter"] = "filter.yml" -# Exclude filter.yml from site building -if "filter.yml" not in data["build"]["content"][0]["exclude"]: - data["build"]["content"][0]["exclude"].append("filter.yml") +# Exclude filter.yml and apidoc folder from build process +# apidoc- this avoids duplicate UID errors from files in the apidoc +# The overwrite mechanism still works +data["build"]["content"][0]["exclude"].extend( + [file for file in ["filter.yml","apidoc/**"] if file not in data["build"]["content"][0]["exclude"]] +) # Imports site resources data["build"]["resource"][0]["files"].extend(