├── .gitignore
├── APLSource
├── NuGet
│ ├── ⎕IO.apla
│ ├── ⎕ML.apla
│ ├── API
│ │ ├── Add.aplf
│ │ ├── Setup.aplf
│ │ ├── Packages.aplf
│ │ ├── Publish.aplf
│ │ ├── Using.aplf
│ │ ├── BinFolder.aplf
│ │ └── Version.aplf
│ ├── IsWin.aplf
│ ├── Version.aplf
│ ├── findfile.aplf
│ ├── NativeFolder.aplf
│ ├── Public.aplf
│ ├── Publish.aplf
│ ├── CmdPaths.aplf
│ ├── BinFolder.aplf
│ ├── CSProjXML.aplf
│ ├── Packages.aplf
│ ├── APLVersion.aplf
│ ├── GetNamespaces.aplf
│ ├── CopyNativeFiles.aplf
│ ├── CMD.aplf
│ ├── Setup.aplf
│ ├── GetDotNetIDS.aplf
│ ├── Add.aplf
│ └── Using.aplf
├── Tests
│ ├── ⎕IO.apla
│ ├── ⎕ML.apla
│ ├── parquet
│ │ ├── userdata1.parquet
│ │ ├── ReadColumns.aplf
│ │ └── Read.aplf
│ ├── test__clock.aplf
│ ├── test__mailkit.aplf
│ ├── test__humanizer.aplf
│ ├── test__selenium.aplf
│ ├── teardown_nuget.aplf
│ ├── test__htmlsanitizer.aplf
│ ├── test_clock.aplf
│ ├── find_nuget_api.aplf
│ ├── test_kafka_wip.aplf
│ ├── test_humanizer.aplf
│ ├── MkUniqueDir.aplf
│ ├── nuget.dyalogtest
│ ├── test.aplf
│ ├── test_htmlsanitizer.aplf
│ ├── setup_nuget.aplf
│ ├── test_parquet.aplf
│ ├── test_mailkit.aplf
│ ├── setup_ResetTempDirs.aplf
│ └── test_selenium.aplf
└── Admin
│ └── Make.aplf
├── .gitattributes
├── apl-package.json
├── cider.config
├── LICENSE
├── CITA.json5
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | Dist
2 |
--------------------------------------------------------------------------------
/APLSource/NuGet/⎕IO.apla:
--------------------------------------------------------------------------------
1 | 1
2 |
--------------------------------------------------------------------------------
/APLSource/NuGet/⎕ML.apla:
--------------------------------------------------------------------------------
1 | 1
2 |
--------------------------------------------------------------------------------
/APLSource/Tests/⎕IO.apla:
--------------------------------------------------------------------------------
1 | 1
2 |
--------------------------------------------------------------------------------
/APLSource/Tests/⎕ML.apla:
--------------------------------------------------------------------------------
1 | 1
2 |
--------------------------------------------------------------------------------
/APLSource/NuGet/API/Add.aplf:
--------------------------------------------------------------------------------
1 | Add←{##.Add ⍵}
2 |
--------------------------------------------------------------------------------
/APLSource/NuGet/API/Setup.aplf:
--------------------------------------------------------------------------------
1 | Setup←{##.Setup ⍵}
2 |
--------------------------------------------------------------------------------
/APLSource/NuGet/API/Packages.aplf:
--------------------------------------------------------------------------------
1 | Packages←{##.Packages ⍵}
2 |
--------------------------------------------------------------------------------
/APLSource/NuGet/API/Publish.aplf:
--------------------------------------------------------------------------------
1 | Publish←{##.Publish ⍵}
2 |
--------------------------------------------------------------------------------
/APLSource/NuGet/API/Using.aplf:
--------------------------------------------------------------------------------
1 | Using←{⍺←⊢ ⋄ ⍺ ##.Using ⍵}
2 |
--------------------------------------------------------------------------------
/APLSource/NuGet/API/BinFolder.aplf:
--------------------------------------------------------------------------------
1 | BinFolder←{##.BinFolder ⍵}
2 |
--------------------------------------------------------------------------------
/APLSource/NuGet/IsWin.aplf:
--------------------------------------------------------------------------------
1 | r←IsWin
2 | r←'win'≡APLVersion 1
3 |
--------------------------------------------------------------------------------
/APLSource/NuGet/Version.aplf:
--------------------------------------------------------------------------------
1 | version←Version
2 | version←'0.2.6'
3 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 | *.apl? linguist-language=APL
3 |
--------------------------------------------------------------------------------
/APLSource/NuGet/API/Version.aplf:
--------------------------------------------------------------------------------
1 | version←Version
2 | version←##.Version
3 |
--------------------------------------------------------------------------------
/APLSource/NuGet/findfile.aplf:
--------------------------------------------------------------------------------
1 | findfile←{{(1=≢⍵)/⊃⍵}⊃0 ⎕NINFO⍠1⊢⍵} ⍝ File name if exactly one found, else ''
2 |
--------------------------------------------------------------------------------
/APLSource/Tests/parquet/userdata1.parquet:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dyalog/nuget/main/APLSource/Tests/parquet/userdata1.parquet
--------------------------------------------------------------------------------
/APLSource/NuGet/NativeFolder.aplf:
--------------------------------------------------------------------------------
1 | r←NativeFolder project_dir;xml;target;RID;TFM
2 | (TFM RID)←GetDotNetIDS ⍬
3 | r←project_dir,'/runtimes/',RID,'/native'
4 |
--------------------------------------------------------------------------------
/APLSource/NuGet/Public.aplf:
--------------------------------------------------------------------------------
1 | r←Public
2 | r←''
3 | r,←⊂'Add'
4 | r,←⊂'Packages'
5 | r,←⊂'Setup'
6 | r,←⊂'Using'
7 | r,←⊂'Version'
8 | r,←⊂'BinFolder'
9 |
10 |
--------------------------------------------------------------------------------
/APLSource/NuGet/Publish.aplf:
--------------------------------------------------------------------------------
1 | {r}←Publish project_dir;z
2 | z←⎕CMD CmdPaths'dotnet publish ',project_dir,' -o ',project_dir,'/published'
3 | r←CopyNativeFiles project_dir
4 |
--------------------------------------------------------------------------------
/APLSource/NuGet/CmdPaths.aplf:
--------------------------------------------------------------------------------
1 | r←CmdPaths p
2 | ⍝ Fix up an argument to ⎕SH for the target platform
3 |
4 | :If IsWin
5 | r←('/'⎕R'\\')p
6 | :Else
7 | r←('\\'⎕R'/')p
8 | :EndIf
9 |
--------------------------------------------------------------------------------
/APLSource/Tests/test__clock.aplf:
--------------------------------------------------------------------------------
1 | r←test__clock nul
2 | ⍝ a cover function for DTest to call the actual test function "test_***" through "test" (which setup NuGet for that specific test)
3 | r←test 6↓1⊃⎕SI
--------------------------------------------------------------------------------
/APLSource/Tests/test__mailkit.aplf:
--------------------------------------------------------------------------------
1 | r←test__mailkit nul
2 | ⍝ a cover function for DTest to call the actual test function "test_***" through "test" (which setup NuGet for that specific test)
3 | r←test 6↓1⊃⎕SI
--------------------------------------------------------------------------------
/APLSource/Tests/test__humanizer.aplf:
--------------------------------------------------------------------------------
1 | r←test__humanizer nul
2 | ⍝ a cover function for DTest to call the actual test function "test_***" through "test" (which setup NuGet for that specific test)
3 | r←test 6↓1⊃⎕SI
--------------------------------------------------------------------------------
/APLSource/Tests/test__selenium.aplf:
--------------------------------------------------------------------------------
1 | r←test__selenium nul
2 | ⍝ a cover function for DTest to call the actual test function "test_***" through "test" (which setup NuGet for that specific test)
3 | r←test 6↓1⊃⎕SI
--------------------------------------------------------------------------------
/APLSource/Tests/teardown_nuget.aplf:
--------------------------------------------------------------------------------
1 | {r}←teardown_nuget nul
2 | r←''
3 | ⍝ 2⎕ndelete tmpDir
4 | ⍝start←{⎕SHELL⍠'Shell' ('CMD.EXE' '/C')⊢'start "" ',⊃8374⌶⍵}
5 | ⍝ start ((⊃160⌶'DYALOG'),'\dyalog.exe') 'MAXWS=1G'
--------------------------------------------------------------------------------
/APLSource/Tests/test__htmlsanitizer.aplf:
--------------------------------------------------------------------------------
1 | r←test__htmlsanitizer nul
2 | ⍝ a cover function for DTest to call the actual test function "test_***" through "test" (which setup NuGet for that specific test)
3 | r←test 6↓1⊃⎕SI
--------------------------------------------------------------------------------
/APLSource/NuGet/BinFolder.aplf:
--------------------------------------------------------------------------------
1 | r←BinFolder project_dir;xml;target
2 | xml←⊃CSProjXML project_dir
3 | target←⊃xml[xml[;2]⍳⊂'TargetFramework';3]
4 | r←({⊃(⎕NEXISTS ⍵)/⍵}(project_dir,'/bin')∘,¨'/Debug' '/Release'),'/',target
5 |
--------------------------------------------------------------------------------
/APLSource/NuGet/CSProjXML.aplf:
--------------------------------------------------------------------------------
1 | (xml filename)←CSProjXML project_dir;xml;a;pfolder
2 | filename←findfile project_dir,'/*.csproj'
3 | (project_dir,' does not contain exactly one .csproj file')⎕SIGNAL(0=≢filename)/11
4 | xml←⎕XML⊃⎕NGET filename
5 |
--------------------------------------------------------------------------------
/APLSource/Tests/test_clock.aplf:
--------------------------------------------------------------------------------
1 | {r}←test_clock project_dir;⎕USING
2 | r←'' ⍝ no checks here - error will be caught when executed throught DTest or in CITA
3 | NuGet.Add project_dir 'Clock/1.0.3'
4 | ⎕USING←NuGet.Using project_dir
5 | 'The time is: ',⍕Clock.UtcNow
6 |
--------------------------------------------------------------------------------
/APLSource/Tests/find_nuget_api.aplf:
--------------------------------------------------------------------------------
1 | ref←find_nuget_api;name
2 | ⍝ Prioritised search for a NuGet API
3 |
4 | :For name :In '##.APLSource' '##.NuGet' '#.NuGet' '⎕SE.Dyalog.NuGet'
5 | :If 9=⎕NC name
6 | →0⊣ref←⍎name
7 | :EndIf
8 | :EndFor
9 |
10 | 'Unable to locate NuGet API' ⎕SIGNAL 6
11 |
--------------------------------------------------------------------------------
/APLSource/NuGet/Packages.aplf:
--------------------------------------------------------------------------------
1 | pkgs←Packages project_dir ;xml;filename;refs
2 | ⍝ Retrieve Package References from the project folder
3 | xml←⊃CSProjXML project_dir
4 |
5 | :If 0=≢refs←xml[⍸xml[;2]∊⊂'PackageReference';4]
6 | pkgs←⍬
7 | :Else
8 | pkgs←{0=≢⍵:'' '' ⋄ ⍵[⍵[;1]⍳'Include' 'Version';2]}¨refs
9 | :EndIf
10 |
--------------------------------------------------------------------------------
/APLSource/Tests/test_kafka_wip.aplf:
--------------------------------------------------------------------------------
1 | {r}←test_kafka_wip project_dir;using;prefixes;path;drvs;drv;p;⎕using
2 | r←'This example doesn''t work yet, please try again later'
3 | →0
4 |
5 | ⎕SE.Link.Create'DKaf' 'c:\devt\DKaf'
6 |
7 | p←⎕NEW DKaf.Producer(⊂'localhost:9092')
8 | p.Produce('dyalog' 'mykey' 'This should be a utf8 string')
9 |
--------------------------------------------------------------------------------
/APLSource/Tests/test_humanizer.aplf:
--------------------------------------------------------------------------------
1 | {r}←test_humanizer project_dir;⎕USING;dt
2 | r←'' ⍝ no checks here - error will be caught when executed throught DTest or in CITA
3 | NuGet.Add project_dir'Humanizer.Core'
4 | ⎕USING←'(includePrimary: 0)'NuGet.Using project_dir
5 | dt←System.DateTime.Parse⊂'31/10/1962'
6 | ⎕←dt.Humanize ⎕NULL(System.DateTime.Now)⎕NULL
7 |
--------------------------------------------------------------------------------
/APLSource/Tests/MkUniqueDir.aplf:
--------------------------------------------------------------------------------
1 | {r}←MkUniqueDir w
2 | ⍝ emulates ⎕MKDIR⍠'Unique' in versions < 20
3 |
4 | :If 20≤2 1⊃'.'⎕VFI 2⊃'#'⎕WG'APLVersion'
5 | ⍝ :If 20≤APLVersion 2 ⍝ neater, but not possible, as this tool is needed before NuGet is loaded
6 | r←⎕MKDIR(⍠'Unique' 1)w
7 | :Else
8 | r←w
9 | :While ⎕NEXISTS r
10 | r,←(⎕A,⎕D)[?36]
11 | :EndWhile
12 | :EndIf
13 |
--------------------------------------------------------------------------------
/APLSource/Tests/parquet/ReadColumns.aplf:
--------------------------------------------------------------------------------
1 | ReadColumns←{
2 | ⍝ ⍺ ←→ Parquet.NET RowGroupReader
3 | ⍝ ⍵ ←→ Parquet.NET Data Field
4 | ⍝ ← ←→ Simple array of data
5 | ct←⎕NEW System.Threading.CancellationToken 0
6 | cd←⍺.ReadColumnAsync ⍵ ct
7 | d←cd.Result.Data
8 | type←¯2↓⊃⌽'.'(≠⊆⊢)⍵.ToString
9 | 'DateTime'≡type:1 ⎕DT⊆d.(Year Month Day Hour Minute Second Millisecond)
10 | ↑d
11 | }
12 |
--------------------------------------------------------------------------------
/APLSource/Admin/Make.aplf:
--------------------------------------------------------------------------------
1 | zipFilename←Make;cfg;noOf;parms
2 | cfg←⎕se.Tatin.ReadPackageConfigFile ##.CiderConfig.HOME
3 | noOf←⎕se.Tatin.CreateAPIfromCFG ##.NuGet cfg
4 | {⍵:.} 5≠noOf ⍝ Expected number of public API functions
5 | parms←⎕se.Tatin.CreateBuildParms ##.CiderConfig.HOME
6 | parms.version←##.NuGet.Version
7 | parms.targetPath←##.CiderConfig.HOME,'/',##.CiderConfig.CIDER.distributionFolder
8 | zipFilename←⎕se.Tatin.BuildPackage parms
9 |
--------------------------------------------------------------------------------
/APLSource/NuGet/APLVersion.aplf:
--------------------------------------------------------------------------------
1 | R←APLVersion sel
2 | ⍝ returns elements of APLVersion specified by sel (see below)
3 | ⍝ passing any other than the supported value simply returns the full APLVersion string
4 | R←'.'⎕WG'APLVersion'
5 | :Select sel
6 | :Case 1 ⍝ sel=1: return leading 3 characters of lowercase platform name
7 | R←⎕C 3↑1⊃R
8 | :Case 2 ⍝ sel=2: return major version no.
9 | R←2 1⊃'.'⎕VFI 2⊃R
10 | :EndSelect
11 |
--------------------------------------------------------------------------------
/APLSource/Tests/nuget.dyalogtest:
--------------------------------------------------------------------------------
1 | DyalogTest : 1.30
2 | ID : nuget
3 | Description: DTest for NuGet
4 |
5 | Setup : setup_nuget
6 |
7 | ⍝ test_kafka and test_parquet are not called - they are WIP currently
8 | ⍝ the "test__*" cover fns are created by setup_n uget
9 | Test : test__clock
10 | Test : test__htmlsanitizer
11 | Test : test__humanizer
12 | Test : test__mailkit
13 | Test : test__selenium
14 |
15 | Teardown: teardown_nuget
--------------------------------------------------------------------------------
/APLSource/NuGet/GetNamespaces.aplf:
--------------------------------------------------------------------------------
1 | r←GetNamespaces name;⎕using;mine;assemblies
2 | ⍝ Return Namespaces which begin with name
3 | ⍝ Note that the namespaces must have been references to be loaded
4 | ⍝ (just setting ⎕USING is not enough)
5 |
6 | ⎕using←'System' 'System.Reflection'
7 | assemblies←AppDomain.CurrentDomain.GetAssemblies
8 | mine←name {(((≢⍺)↑¨⍕¨⍵)∊⊂⍺)/⍵} assemblies
9 | :If 0≠≢mine
10 | r←mine.GetExportedTypes.ToString
11 | :Else
12 | r←0⍴⊂''
13 | :EndIf
14 |
--------------------------------------------------------------------------------
/APLSource/NuGet/CopyNativeFiles.aplf:
--------------------------------------------------------------------------------
1 | {r}←CopyNativeFiles project_dir;target;native;n
2 |
3 | :If ⎕NEXISTS native←NativeFolder project_dir
4 | :If 0≠≢findfile (target←project_dir),'/*.deps.json'
5 | :OrIf 0≠≢findfile (target←project_dir,'/published'),'/*.deps.json'
6 | n←target ⎕NCOPY⍠('IfExists' 'Skip')('Wildcard' 1)⊢native,'/*'
7 | :Else
8 | 'Unable to locate target directory' ⎕SIGNAL 11
9 | :EndIf
10 | r←(⍕n),' new native files copied from ',native
11 | :Else
12 | r←'no native files to copy'
13 | :EndIf
14 |
--------------------------------------------------------------------------------
/apl-package.json:
--------------------------------------------------------------------------------
1 | {
2 | api: "API",
3 | assets: "",
4 | description: "Use NuGet packages from Dyalog APL",
5 | documentation: "",
6 | exclude: "⎕IO.apla,⎕ML.apla",
7 | files: "",
8 | group: "dyalog",
9 | io: 1,
10 | license: "MIT",
11 | lx: "",
12 | maintainer: "support@dyalog.com",
13 | minimumAplVersion: "19.0",
14 | ml: 1,
15 | name: "NuGet",
16 | os_lin: 1,
17 | os_mac: 1,
18 | os_win: 1,
19 | project_url: "https://github.com/dyalog/nuget",
20 | source: "APLSource/NuGet",
21 | tags: "dotnet,nuget,packages",
22 | userCommandScript: "",
23 | version: "0.2.6",
24 | }
25 |
--------------------------------------------------------------------------------
/cider.config:
--------------------------------------------------------------------------------
1 | {
2 | CIDER: {
3 | cider_version: "0.41.1",
4 | dependencies: {
5 | nuget: "",
6 | tatin: "",
7 | },
8 | dependencies_dev: {
9 | tatin: "",
10 | },
11 | distributionFolder: "Dist",
12 | init: "",
13 | make: "Admin.Make",
14 | parent: "#",
15 | projectSpace: "NuGet",
16 | project_url: "https://github.com/dyalog/nuget",
17 | source: "APLSource",
18 | tatinVars: "NuGet",
19 | tests: "",
20 | version: "0.2.6",
21 | },
22 | LINK: {
23 | },
24 | SYSVARS: {
25 | io: 1,
26 | ml: 1,
27 | },
28 | USER: {
29 | },
30 | }
31 |
--------------------------------------------------------------------------------
/APLSource/NuGet/CMD.aplf:
--------------------------------------------------------------------------------
1 | r←CMD cmd;qdmx;⎕RL;tempFilename
2 | ⍝ Cover function for ⎕CMD. Deals with the fact that ⎕CMD behaves differently on Windows compared with Linux and Mac OS
3 | r←''
4 | ⎕RL←⍬
5 | tempFilename←(739⌶0),'/',⎕AN,'-',⍕100000+?10000000
6 | :Trap 11
7 | r←⎕CMD cmd,'>',tempFilename,' 2>&1'
8 | :If 0=≢r
9 | :If ⎕NEXISTS tempFilename
10 | r←⊃⎕NGET tempFilename 1
11 | :Else
12 | 'Something went wrong'⎕SIGNAL 11
13 | :EndIf
14 | :EndIf
15 | :Else
16 | qdmx←⎕DMX
17 | :If ⎕NEXISTS tempFilename
18 | r←⊃⎕NGET tempFilename 1
19 | :Else
20 | 3 ⎕NDELETE tempFilename
21 | qdmx.EM ⎕SIGNAL qdmx.EN
22 | :EndIf
23 | :EndTrap
24 | 3 ⎕NDELETE tempFilename
25 | ⍝Done
26 |
--------------------------------------------------------------------------------
/APLSource/Tests/test.aplf:
--------------------------------------------------------------------------------
1 | {r}←test name;folder;NuGet;R;⎕USING
2 | ⍝ localizes ⎕USING just in case a test does not...
3 | r←''
4 | :If 0=≢name
5 | ⎕←'The current test functions exist:'
6 | ⎕←{(1=+/¨'_'=⍵)/⍵}'t'⎕NL-3
7 | →0
8 | :EndIf
9 | :If 0=⎕NC'tmpDir' ⍝ is created in setup_nuget, may not available when used in the session...
10 | tmpDir←MkUniqueDir(739⌶0),'/NuGet_'
11 | :EndIf
12 |
13 | NuGet←find_nuget_api
14 | :For name :In ⊆name
15 | 'No such test'⎕SIGNAL(3≠⎕NC'test_',name)/6
16 | folder←MkUniqueDir tmpDir,'/',name ⍝ unique folder for this test is created in tmpDir (which is deleted by "teardown_nuget")
17 | NuGet.Setup folder
18 | ⍎'R←test_',name,' folder'
19 | :If 0<≢∊R
20 | r,←(⊂' test_',name,': '),¨⊆R
21 | :EndIf
22 | :EndFor
23 |
--------------------------------------------------------------------------------
/APLSource/Tests/test_htmlsanitizer.aplf:
--------------------------------------------------------------------------------
1 | {r}←test_htmlsanitizer project_dir;⎕USING;hs;html;sanitized;expected
2 | r←''
3 | NuGet.Add project_dir'HtmlSanitizer'
4 | ⎕USING←NuGet.Using project_dir
5 | hs←⎕NEW Ganss.Xss.HtmlSanitizer
6 |
7 | html←'
Test

'
10 |
11 | sanitized←hs.Sanitize html'https://www.example.com'⎕NULL
12 |
13 | expected←''
14 | expected,←'Test

'
15 |
16 | :If expected≡sanitized
17 | ⎕←'it works!'
18 | :Else
19 | r←'sanitization failed'
20 | :EndIf
21 |
--------------------------------------------------------------------------------
/APLSource/Tests/setup_nuget.aplf:
--------------------------------------------------------------------------------
1 | {r}←setup_nuget nul;bp;path;file;f;d2;z
2 | r←''
3 | path←({1⊃⎕NPARTS{(-'/\'∊⍨⊢/⍵)↓⍵}⍵}⍣2)##.TESTSOURCE ⍝ go back to grandpa's folder...
4 | ⍝ build the NuGet package and load it - so that we test against the built package (to find functions not included in the API etc.)
5 | bp←⎕SE.Tatin.CreateBuildParms path
6 | file←setup_ResetTempDirs ##.TESTSOURCE
7 | tmpDir←MkUniqueDir(739⌶0),'/NuGet_' ⍝ must be global! (see "test")
8 | (⊂tmpDir)⎕NPUT file 2 ⍝ tempdirs.txt contains all temp dirs created for tests - they'll be deleted in setup_ResetTempDirs
9 | bp.targetPath←tmpDir
10 | ⎕←⎕this
11 | z←{⎕SE.Tatin.(LoadPackages(BuildPackage ⍵)('#'))}bp
12 | ⎕←⎕this
13 | 1 Assert z ⍝ was one package loaded?
14 | f←⎕NL ¯3
15 | f←{((⊂'test_')≡¨5↑¨⍵)/⍵}f
16 | {⎕FX('r←test_',4↓⍵)'r←test 6↓1⊃⎕SI'}¨f
17 |
--------------------------------------------------------------------------------
/APLSource/Tests/test_parquet.aplf:
--------------------------------------------------------------------------------
1 | {r}←test_parquet project_dir;path;z;colnames;data;trap;⎕using
2 | r←'' ⍝ no checks here - error will be caught when executed throught DTest or in CITA
3 | trap←0 ⍝ do not catch errors by default
4 | :If 2=⎕NC'##.halt' ⍝ unless ##.halt exists (DTest's flag)
5 | :AndIf ##.halt=0 ⍝ and isn't set to 1
6 | trap←1
7 | :EndIf
8 | :Trap trap/0 ⍝ this test is currently not working, so at least catch the error (unless we run with the "-halt" flag in DTest)
9 | NuGet.Add project_dir'Parquet.Net'
10 | parquet.⎕USING←(NuGet.Using project_dir),⊂'System.IO,System.IO.FileSystem,System.IO.Stream'
11 |
12 | path←(⊃⎕NPARTS 4⊃5179⌶⊃⎕SI),'parquet/'
13 | (data colnames)←parquet.Read path,'userdata1.parquet'
14 | colnames,[0.5]⍪¨10↑¨data
15 | :Else
16 | r←⎕DM
17 | :EndTrap
18 |
--------------------------------------------------------------------------------
/APLSource/Tests/parquet/Read.aplf:
--------------------------------------------------------------------------------
1 | Read←{
2 | ⍝ ⍵ ←→ path to .parquet file
3 | ⍝ ← ←→ (data) (header)
4 | ⍝ ⍵ :: simple char vec
5 | ⍝ data :: inverted table of simple vectors or matrices
6 | ⍝ header :: is a nested vector of character vectors
7 |
8 | ⍝ === NOTE ===
9 | ⍝ currently reads a single inverted table from a single row group
10 | ⍝ parquet files may be more complex, design is required
11 | ⍝ for now users can use the following code as a translation template for the low-level API provided
12 | ⍝ https://github.com/aloneguid/parquet-dotnet
13 |
14 | fs←File.OpenRead⊆⍵
15 | ct←⎕NEW System.Threading.CancellationToken 0
16 | pr←Parquet.ParquetReader.CreateAsync fs ⎕NULL 0 ct
17 | reader←pr.Result
18 | X←((~∊⍨)⊆⊢) ⋄ nl←⎕UCS 10 13
19 | header←⊃¨' 'X¨nl X reader.Schema.ToString
20 | rgr←reader.OpenRowGroupReader 0
21 | data←rgr∘ReadColumns¨reader.Schema.GetDataFields
22 |
23 | data header
24 | }
25 |
--------------------------------------------------------------------------------
/APLSource/NuGet/Setup.aplf:
--------------------------------------------------------------------------------
1 | r←Setup project_dir;csproj;xml;project_name;TFM;RID;pkgs;z
2 | :If 0=⎕NC'force' ⋄ force←0 ⋄ :EndIf
3 | project_name←'_',{(1-⌊/(⌽⍵)⍳'\/')↑⍵}project_dir
4 |
5 | (TFM RID)←GetDotNetIDS ⍬
6 | :If 'net4'≡4↑TFM
7 | ('dotnet ',TFM,' currently not supported')⎕SIGNAL 11
8 | :EndIf
9 | ⍝ Ask dotnet to create a .csproj file
10 |
11 | :If ⎕NEXISTS csproj←project_dir,'/',project_name,'.csproj'
12 | r←'Project file "',csproj,'" already exists '
13 | :If 0=≢pkgs←Packages project_dir
14 | r,←' (no packages)'
15 | :Else
16 | r,←'with package(s): ',(¯1↓2↓∊', '∘,¨⍕¨pkgs)
17 | :EndIf
18 | →0
19 | :EndIf
20 |
21 | z←↑⎕CMD CmdPaths'dotnet new classlib --target-framework-override ',TFM,' --output ',project_dir,' --name ',project_name
22 | (xml csproj)←CSProjXML project_dir
23 | :If ~(⊂'LangVersion')∊xml[;2] ⍝ Add latest LangVersion
24 | xml⍪←2 'LangVersion' 'Latest'⍬ 5
25 | (⊂⎕XML xml)⎕NPUT csproj 1
26 | :EndIf
27 |
28 | r←'Created project file "',csproj,'"'
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Dyalog
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/APLSource/Tests/test_mailkit.aplf:
--------------------------------------------------------------------------------
1 | {r}←test_mailkit project_dir;server;user;pass;ct;client;starttls;i;n;msg;⎕USING
2 | r←''
3 | server←'mail.dyalog.com'
4 | user←'qa-internal@dyalog.com'
5 | :If 0=≢pass←2 ⎕NQ'.' 'GetEnvironment' 'POP3_QA_INTERNAL'
6 | r←'Environment variable POP3_QA_INTERNAL not set - cannot run test_mailkit'
7 | →0
8 | :EndIf
9 |
10 | NuGet.Add project_dir'MimeKit/3.5.0' 'MailKit/3.5.0'
11 | ⎕USING←'System.Threading' 'MailKit.Net.Pop3',NuGet.Using project_dir
12 | ct←⎕NULL ⍝ Alternatively (⎕NEW CancellationToken 0)
13 |
14 | client←⎕NEW Pop3Client
15 | starttls←MailKit.Security.SecureSocketOptions.StartTls
16 | client.Connect server 110 starttls ct
17 |
18 | :Trap 90
19 | client.Authenticate user pass ct
20 | :Else
21 | r←'Unable to authenticate as ',user,' on server ',server
22 | →0
23 | :EndTrap
24 |
25 | ⎕←'You have ',(⍕n←client.Count),' message(s)'
26 |
27 | :For i :In ⍳n
28 | msg←client.GetMessage(i-1)⎕NULL ⎕NULL ⍝ null CancellationToken and ITransferProgress
29 | '[',(⍕i),']'
30 | 'From ',msg.From
31 | 'To ',msg.To
32 | 'Subject: ',msg.Subject
33 | ⎕←' '
34 | msg.TextBody
35 | ⎕←' '
36 | :EndFor
37 |
--------------------------------------------------------------------------------
/APLSource/NuGet/GetDotNetIDS.aplf:
--------------------------------------------------------------------------------
1 | (TFM RID)←GetDotNetIDS dummy;⎕USING;major;minor;fd;dnv;arch;os;ok;netstatus
2 | ⍝ Return DotNet
3 | ⍝ TFM: Target Framework Moniker (net4N for Framework, netcoreapp3.N, or netN.0 for 6-8) : https://learn.microsoft.com/en-us/dotnet/standard/frameworks
4 | ⍝ RID: Runtime Identifier (win|mac|linux-x64|x86|arm64) : https://learn.microsoft.com/en-us/dotnet/core/rid-catalog
5 |
6 | :If ~ok←2⊃netstatus←2250⌶⍬
7 | ('No .NET available. 2250⌶ returned ',⍕netstatus) ⎕SIGNAL ok↓11
8 | :EndIf
9 | ⎕USING←''
10 |
11 | (major minor)←System.Environment.Version.(Major Minor)
12 | dnv←(⍕major),'.',⍕minor
13 | 'Minimum .NET version is 3.0'⎕SIGNAL(3>major)/11
14 | :Select major
15 | :Case 3 ⍝ "core"
16 | TFM←'netcoreapp',dnv
17 |
18 | :Case 4 ⍝ Framework: see if we can get more detailed information
19 | :If 0≠≢fd←{0::⍵ ⋄ System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription}''
20 | arch←System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture
21 | dnv←∊2↑'.'(≠⊆⊢)⊃⌽' '(≠⊆⊢)fd
22 | :EndIf
23 | TFM←'net',dnv∩⎕D
24 | :Else ⍝ 5+
25 | TFM←'net',dnv
26 | :EndSelect
27 |
28 | :If major≠4 ⍝ Framework has this in corelib
29 | ⎕USING←',System.Runtime',(major<7)/'.InteropServices.RuntimeInformation'
30 | :EndIf
31 | arch←System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture
32 |
33 | os←APLVersion 1
34 | os,←(⊃('win' 'mac' 'linux' '')['win' 'mac' 'lin'⍳⊂os])
35 | 'unidentified OS'⎕SIGNAL(0=≢os)/11
36 |
37 | RID←⎕C os,'-',⍕arch
38 |
--------------------------------------------------------------------------------
/APLSource/NuGet/Add.aplf:
--------------------------------------------------------------------------------
1 | r←{opt}Add args;project_dir;newpkgs;new;p;newv;old;oldv;pkgs;i;same;bad;add;z;mask;v;cmd
2 | ⍝ ⊃args: project_dir
3 | ⍝ 1↓args: new packages, either 'name' or 'name/version'
4 | ⍝ e.g. Add 'c:\tmp\clocktest\ 'Clock'
5 | ⍝ opt is a boolean flag (Default=1) that controls if we should Publish the project.
6 |
7 | args←,⊆args
8 | project_dir←⊃args
9 | :If 0=⎕NC'opt'
10 | opt←1
11 | :EndIf
12 | ('directory not found: ',project_dir)⎕SIGNAL(⎕NEXISTS project_dir)↓11
13 | ('not a directory: ',project_dir)⎕SIGNAL(1=1 ⎕NINFO project_dir)↓11
14 | project_dir,←('/\'∊⍨⊢/project_dir)↓'/'
15 |
16 | newpkgs←1↓args
17 | new←(¯1+p←newpkgs⍳¨'/')↑¨newpkgs
18 | newv←p↓¨newpkgs
19 |
20 | (old oldv)←↓⍉↑pkgs←Packages project_dir
21 |
22 | i←⍸(new∊old)∧0=≢¨newv ⍝ Actually already registered and version not specified
23 | newv[i]←oldv[old⍳new[i]] ⍝ Update to existing version
24 |
25 | same←⍸new∊old ⍝ Already registered
26 | same←(⍳≢new)∊(newv[same]≡oldv[old⍳new[same]])/i ⍝ With the same version
27 | ⍝ research suggests the following is wrong, just "dotnet add" again to change version
28 | ⍝:If 0≠≢i←i/⍨newv[i]≢oldv[old⍳new[i]]
29 | ⍝ ('already registered with a different version: ',,⍕pkgs[old⍳new[i]])⎕SIGNAL 11
30 | ⍝:EndIf
31 |
32 | bad←0⍨¨new
33 | r←''
34 | r,←'Already registered: '∘,¨same/new
35 | :For i :In ⍸~same
36 | add←(i⊃new),(0≠≢v)/' --version ',v←i⊃newv
37 | cmd←'dotnet add ',project_dir,' package ',add
38 | z←CMD cmd
39 | mask←∨/¨'error: '∘⍷¨z
40 | :If bad[i]←∨/mask
41 | r,←⊂'Error: ',add
42 | r,←mask/z
43 | :Else
44 | r,←⊂'Added/Updated: ',add
45 | :EndIf
46 | :EndFor
47 |
48 | :If opt∧bad∧.⍱same ⍝ Publish if something was added
49 | z←Publish project_dir ⍝ Returns contents of published folder
50 | :EndIf
51 | r←⍪r
52 |
--------------------------------------------------------------------------------
/APLSource/Tests/setup_ResetTempDirs.aplf:
--------------------------------------------------------------------------------
1 | file←setup_ResetTempDirs folder;d2;f;v
2 | ⍝ The challenge is that every test creates a temp dir in order to execute NuGet with an empty project folder.
3 | ⍝ But our very own "teardown" will not be able to delete these folder as they may still be locked by still having links
4 | ⍝ to the dlls. With .NET Framework, there is a way to deal with it ("close appdomain"), but that's not
5 | ⍝ available with .NET Core. So the solution for both cases is to maintain a persistent list of temp dirs
6 | ⍝ and then at the beginning of a test run, we try to delete them. (Likely "leftovers" from previous session.)
7 | v←0
8 | :If 2=⎕NC'##.verbose'
9 | :AndIf ##.verbose
10 | v←1
11 | :EndIf
12 | :If ⎕NEXISTS file←folder,'tempdirs.txt' ⍝ if the file exists
13 | d2←⍬
14 | :For f :In 1⊃⎕NGET file 1
15 | :If '//'≢2↑f ⍝ ignore line comments
16 | :Select {0::¯2 ⋄ ~⎕NEXISTS ⍵:¯1 ⋄ 2⎕NDELETE ⍵}f
17 | :Case ¯2 ⍝ error deleting folder (permissions or locked files etc.)
18 | d2,←⊂f ⍝ keep it in the list
19 | :If v
20 | ⎕←'Error deleting "',f,'" - will keep in list'
21 | ⎕←(⎕json⍠'Compact'0) ⎕dmx
22 | :EndIf
23 | :Case ¯1 ⍝ does not exist (nothing to do)
24 | :If v
25 | ⎕←'"f" does not exist - removed from list'
26 | :EndIf
27 | :Case 1 ⍝ successful delete (0 )
28 | :If v
29 | ⎕←'Deleted temp dir:',f
30 | :EndIf
31 | :Case 0 ⍝ hmm, is that even possible?
32 | d2,←⊂f ⍝ keep it in the list anyway to try again later
33 | :EndSelect
34 | :Else
35 | d2,←⊂f ⍝ keep comments in the list
36 | :EndIf
37 | :EndFor
38 | :If 2<≢d2
39 | (⊂d2)⎕NPUT file 1
40 | :Else
41 | ⎕NDELETE file
42 | →createFile
43 | :EndIf
44 | :Else
45 | createFile:
46 | (⊂'// This file contains all temp dirs created for tests - ideally to be deleted in teardown_nuget' '// but because of locked files this may not possible in the same session - so we maintain a persistent list and check it before a new run...')⎕NPUT file
47 | :EndIf
48 |
--------------------------------------------------------------------------------
/CITA.json5:
--------------------------------------------------------------------------------
1 | {
2 | "defaults": { // all of these entries can also be provided (and tweaked) per test.
3 | // btw: casing of names is not important
4 | "bits": [32,64], // if you want to bind tests to specific bitness
5 | //"context":"C|o|Q", // can be left out, might be needed in very special cases...
6 | // "env": {
7 | // "foo": "goo" // specific environment vars or config settings
8 | // }
9 | "dyalogversions": "19-", // you may want to change this at the level of individual tests...
10 | "editions":["unicode"], // ..or editions
11 | //*** YOU NEED TO PICK ONE EMAIL ENTRY ONLY! ***
12 | //"email": "me@dyalog.com", // send test result to... (can be as simple as this)
13 | "email": ["committer"], // or a list of addresses
14 | //"email": { // and an object with specific fields
15 | // "Error|OK|All|Change": ["me@dyalog.com"], // for various results ("NB": "change" not yet supported)
16 | // } ,
17 | // "net": ["none","default", // you may want to associate certain tests with specific versions of .NET
18 | // "3.1","4.8",
19 | // "6.0","7.0","8.0"],
20 | "platforms": ["win"],
21 | "secondstimeout": 180, // 5 minutes - might be too short for some tests, adjust if needed!
22 | "usehmon":0, // experimental: use health monitor to collect info while test is running
23 | "jenkins_secrets": { // one or more Jenkins Secrets that will be available when the test runs
24 | id: "f01100d7-6953-426a-990c-167cc9f36368", // id
25 | name: "POP3_QA_INTERNAL", // value will be acccessible through this environment variable
26 | }
27 | },
28 | "tests": [
29 | {
30 | "id": "nuget",
31 | "test": "./APLSource/Tests/nuget.dyalogtest",
32 | }
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/APLSource/Tests/test_selenium.aplf:
--------------------------------------------------------------------------------
1 | {r}←test_selenium project_dir;using;prefixes;path;drv;exp;⎕USING;pwf;os
2 | r←'' ⍝ no checks here - error will be caught when executed throught DTest or in CITA
3 | ⍝ we test to stepwise add libraries to the project (avoiding the "Publish" step)
4 | 0 NuGet.Add project_dir'Selenium.WebDriver'
5 | 0 NuGet.Add project_dir'Selenium.WebDriver.ChromeDriver'
6 | ⍝ the next one is a bit tricky because we need to a version of the library that matches the version of the WebDriver that was loaded.
7 | ⍝ we didn't specify one when loading the WebDriver - so Selenium4 fetched the one that matches our browser!
8 | ⍝ Our .csproj will have a line like this:
9 | ⍝
10 | ⍝ ↑↑↑↑↑↑ and that is the info we need! regex below will extract it....
11 | 0 NuGet.Add project_dir('Selenium.Support/',⊃('"Selenium.WebDriver" Version="(.*)"'⎕S'\1')1⊃⎕NGET{⎕←⍵,'/_',(2⊃⎕NPARTS ⍵),'.csproj'}project_dir)
12 | 0 NuGet.Add project_dir'WebDriverManager/2.17.6'
13 | NuGet.Publish project_dir
14 | prefixes←'OpenQA' 'OpenQA.Selenium' 'OpenQA.Selenium.Chrome' 'OpenQA.Selenium.Support.UI' 'WebDriverManager' 'WebDriverManager.DriverConfigs.Impl' 'WebDriverManager.Helpers' ⍝ paths into libraries that we need in ⎕USING
15 | ⎕USING←'System' 'System.Drawing,System.Drawing.Primitives' 'System.IO,System.IO.dll',prefixes,NuGet.Using project_dir
16 | path←(NuGet.BinFolder project_dir),'/chromedriver',('win'≡⎕C 3↑1⊃# ⎕WG'APLVersion')/'.exe'
17 |
18 | :Select ⎕C 3↑1⊃'.'⎕WG'APLVersion'
19 | :Case 'win'
20 | os←'windows'
21 | :Case 'mac'
22 | os←'macos'
23 | :Case 'lin'
24 | os←'linux'
25 | :Else
26 | ('Unknow OS: ',⎕C 3↑1⊃'.'⎕WG'APLVersion')⎕SIGNAL 11
27 | :EndSelect
28 | Environment.SetEnvironmentVariable('SE_MANAGER_PATH'({'\'@('/'∘=)⍵}⊃⊃0(⎕NINFO⍠('Recurse' 1)('Wildcard' 1))(project_dir,'/selenium-manager*.*')))
29 |
30 | ⍝ we're simply creating a new instance - SeleniumManager ensures it's compatible with the locally installed version (requires chrome to be installed, though)
31 | drv←⎕NEW ChromeDriver
32 | drv.Url←'https://dyalog.com'
33 | ⎕DL 5
34 | :If drv.Title≢exp←'Home - Dyalog'
35 | r←'did not get expected page title "',exp,'" but "',drv.Title,'"'
36 | :Else
37 | ⎕←'Successfully loaded ',drv.Title
38 | :EndIf
39 |
40 | pwf←⎕NEW PopupWindowFinder drv ⍝ simple check if the fn from Support.UI is available (will error otherwise)
41 |
42 | drv.Quit
43 |
--------------------------------------------------------------------------------
/APLSource/NuGet/Using.aplf:
--------------------------------------------------------------------------------
1 | using_paths←{opts} Using project_dir;deps;d;k;v;t;pkg_name;pkgrt;dll;pkgs;ns;jsname;tgts;z;dlls;children;p;folder;name;opts;opts_mat;all_pkgs;keys;vals;def_opts;includePrimary;includePkgs;excludePkgs
2 | ⍝ Return list of DLL paths for ⎕USING based on a primary DLL and the direct dependencies for a dotnet project published via NuGet
3 | ⍝ args is expected to have one of three forms:
4 | ⍝ 1. a string signifying the project directory; or
5 | ⍝ 2. a list with the project directory as first element and a key-value pairs as other elements; or
6 | ⍝ 3. a list of key-value pairs
7 | ⍝
8 | ⍝ The key-value part of args is interpreted as a map from options to values. Currently the following options are supported:
9 | ⍝ * project_dir is the project directory; it must be signified if args is a pure list of key-value pairs
10 | ⍝ * include_primary is a boolean signifying whether (1) or not (0) the path to the primary DLL is included in the output.
11 | ⍝ Its standard value is 1.
12 | ⍝ * exclude_pkgs is a list of package names (without version number!) to be excluded in the output
13 | ⍝ Its standard value is ⍬
14 | ⍝ * include_pkgs is a list of package names (without version number!) to be included in the output
15 | ⍝ Its standard value is ⍬
16 | ⍝ The parameter exclude_pkgs takes precedence over include_pkgs and giving include_pkgs a value of ⍬ means to include all packages.
17 |
18 | def_opts←⎕NS ''
19 | def_opts.(includePrimary includePkgs excludePkgs)←1 ⍬ ⍬
20 | :Select ⊃⎕NC 'opts'
21 | :Case 0
22 | opts←⎕NS ''
23 | :Case 2
24 | opts←⎕SE.Dyalog.Array.Deserialise opts
25 | :EndSelect
26 | 'def_opts' ⎕NS opts
27 | (includePrimary includePkgs excludePkgs)←def_opts.(includePrimary includePkgs excludePkgs)
28 |
29 | jsname←7162⌶ ⍝ JSON Translate Name
30 |
31 | pkgs←(~excludePkgs∊⍥⎕C⍨1⊃¨all_pkgs)/all_pkgs←Packages project_dir
32 | :If 0<≢includePkgs
33 | pkgs←(includePkgs∊⍥⎕C⍨1⊃¨pkgs)/pkgs
34 | :EndIf
35 |
36 |
37 | :If 0≠≢deps←findfile project_dir,'/*.deps.json'
38 | :OrIf 0≠≢deps←findfile project_dir,'/published/*.deps.json'
39 |
40 | (d k v t)←↓⍉⎕JSON ⎕OPT'Format' 'M'⊃⎕NGET deps
41 | ⍝ Depth, Key, Value, Type
42 | {}2{p[⍵]←⍺[⍺⍸⍵]}⌿⊢∘⊂⌸d⊣p←⍳≢d ⍝ Parent vector p
43 | ⍝ Descendant of pkgs and key≡"runtime"
44 | pkg_name←⎕C⊃¨'/'(≠⊆⊢)¨k ⍝ e.g. Clock/1.0.3 → Clock
45 | pkgrt←(k∊⊂'runtime')(∧⍤1){⍵∨⍵[p]}⍤1⍣≡pkg_name(∊⍤1 0)⊃¨⎕C pkgs
46 | ⍝ Child of "runtime" key is path to .dll
47 | ⍝ file name key parent is "runtime"
48 | ⍝ dll←⊃∘⌽¨'/'(≠⊆⊢)¨k⌿⍤1⍨(⊂p)⌷⍤1⊢pkgrt
49 | dll←∊¨1↓¨⎕NPARTS(∨⌿pkgrt[;p])/k
50 | using_paths←(project_dir,'/published/')∘,¨dll
51 |
52 | (folder name)←2↑⎕NPARTS ¯10↓deps
53 |
54 | ⍝ Possibly include primary DLL
55 | :If includePrimary
56 | :AndIf ⎕NEXISTS dll←(∊folder name),'.dll'
57 | using_paths,←⊂dll
58 | :EndIf
59 |
60 | :Else ⍝ No deps.json file
61 | 'NuGet support currently requires .NET 6.0 or later' ⎕SIGNAL (2=⊃2250⌶0)/11
62 | 'Unable to locate deps.json file' ⎕SIGNAL 11 ⍝ /// Different strategy required for Framework
63 | using_paths←{(~(2⊃¨⎕NPARTS ⍵)∊⊂project_name)/⍵}(⊃⎕NINFO⍠1⊢project_dir,'/published/*.dll')
64 | :EndIf
65 | using_paths←',',¨using_paths
66 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NuGet
2 |
3 | A tool to help use NuGet packages from Dyalog APL.
4 |
5 | This code is used by [Cider](https://github.com/aplteam/Cider) to support NuGet packages as project dependencies. It requires Dyalog v19.0 and .NET 6.0 or later.
6 |
7 | The code can also be used outside of Cider, but documentation is currently rudimentary, consisting only in the form of this README file and the example code in the `Tests/` folder.
8 |
9 | ## Introduction
10 | The NuGet tool works by tapping into the "dotnet" command line tool to establish a folder as a .NET project, and use tools built in to .NET to load NuGet packages. It requires .NET 6.0 or later, and Dyalog APL must be configured to use the new .NET by setting DYALOG_NETCORE=1.
11 |
12 | ## Using NuGet with Cider
13 |
14 | Please refer to the Cider documentation for instructions. At the time this was written, the user command to set up a NuGet dependency was `]CIDER.AddNuGetDependencies`.
15 |
16 | ## Brief API documentation
17 |
18 | ### `NuGet.Setup projectdir`
19 | Makes the initial call to the dotnet command to create a .NET project in the named directory. This must be called first. Example:
20 |
21 | ```
22 | NuGet.Setup '/tmp/nuget-test'
23 | Created project file "/tmp/nuget-test/nuget-test.csproj"
24 | ```
25 |
26 | ### `{pub}NuGet.Add projectdir packageid`
27 |
28 | Adds a NuGet package as a dependency of the project found in the named directory and (optionally) publishes the package. The package name can optionally be followed by a version number; if no version is provided the latest will be used. Example:
29 |
30 | ```
31 | NuGet.Add '/tmp/nuget-test' 'Clock/1.0.3'
32 | Added/Updated: Clock
33 | ```
34 |
35 | The optional left argument `pub`can be used to control whether the package should be
36 | published (1, default) or not (0). When adding several packages, you can save time by not publishing during the individual `Add`s, but by using `pub=0` and calling `Publish` afterwards.
37 |
38 | ### `NuGet.BinFolder projectdir`
39 |
40 | Returns the fully qualified path to the binary output directory for a .NET project.
41 |
42 | The function prioritizes Debug builds if both Debug and Release folders exist. The target framework (e.g., net6.0, net8.0) is automatically appended to create the complete binary path.
43 |
44 | ### `⎕USING←NuGet.Using projectdir`
45 |
46 | Returns the ⎕USING setting that will make it possible to reference the entry points of the added packages. Example:
47 |
48 | ```
49 | ]box on
50 | Was OFF
51 | NuGet.Using project_dir
52 | ┌────────────────────────────────────┬─────────────────────────────────────────┐
53 | │,/tmp/nuget-test/published/Clock.dll│,/tmp/nuget-test/published/nuget-test.dll│
54 | └────────────────────────────────────┴─────────────────────────────────────────┘
55 | ```
56 |
57 | If you do not want to include the DLL which represents the empty C# executable that was created by the dotnet command, you can specify this as follows:
58 |
59 | ```
60 | '(includePrimary: 0)' NuGet.Using project_dir
61 | ┌────────────────────────────────────┐
62 | │,/tmp/nuget-test/published/Clock.dll│
63 | └────────────────────────────────────┘
64 | ```
65 |
66 | ### `NuGet.Packages projectdir`
67 |
68 | Returns the current list of dependencies::
69 |
70 | ```
71 | NuGet.Packages project_dir
72 | ┌─────────────┐
73 | │┌─────┬─────┐│
74 | ││Clock│1.0.3││
75 | │└─────┴─────┘│
76 | └─────────────┘
77 | ```
78 |
79 | ### `NuGet.Publish projectdir`
80 |
81 | Publishes the project and its dependencies to a `/published` folder within the project directory. This step is automatically performed when adding packages (unless disabled with `pub=0` in `Add`), but can be called separately when needed.
82 |
83 | ### `NuGet.Version`
84 |
85 | Returns the current NuGet version number:
86 |
87 | ```
88 | NuGet.Version
89 | 0.2.0
90 | ```
91 |
92 |
93 | ## Running the Tests
94 |
95 | To run the tests in Dyalog version 19.0, you must:
96 |
97 | * Make sure you have installed .NET 6.0 or later and set the configuration parameter DYALOG_NETCORE=1 (this is the default under Linux and macOS but not under Windows)
98 | * Either load the Tatin package using `]TATIN.LoadPackages dyalog-nuget`, followed by `]get https://github.com/dyalog/nuget/tree/main/APLSource/Tests`, or
99 | * `]get https://github.com/dyalog/nuget/tree/main/APLSource -unpack`, which will establish both `NuGet` and `Tests` in the workspace.
100 |
101 | To get a list of runnable tests:
102 |
103 | ```
104 | Tests.test ''
105 | The current test functions exist:
106 | test_clock test_humanizer test_htmlsanitizer test_mailkit test_parquet test_selenium
107 | ```
108 |
109 | To run a test:
110 |
111 | ```
112 | Tests.test 'selenium'
113 | Created project file "/tmp/nuget-test/nuget-test.csproj"
114 | Added/Updated: Selenium.WebDriver Selenium.WebDriver.ChromeDriver
115 | Successfully loaded Dyalog - Home
116 | ```
117 |
118 | Note that you cannot run more than one test per APL session, because once the DLL's are loaded by the interpreter, there is currently no way to unload them.
--------------------------------------------------------------------------------