galaaz 0.5.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -0
- data/LICENSE +0 -0
- data/README.md +1416 -667
- data/Rakefile +68 -41
- data/bin/galaaz-bootstrap +137 -0
- data/bin/galaaz-jruby +11 -0
- data/bin/galaaz-ruby +16 -0
- data/bin/galaaz_jruby_env.inc.sh +6 -0
- data/bin/galaaz_ruby_env.inc.sh +36 -0
- data/bin/gbookdown +63 -0
- data/bin/gknit +83 -13
- data/bin/gknit-draft.rb +0 -0
- data/bin/gstudio +5 -3
- data/bin/gstudio_irb.rb +0 -0
- data/bin/gstudio_pry.rb +0 -0
- data/bin/install-tinytex +6 -0
- data/bin/run_all_rspec +44 -0
- data/bin/run_example +17 -0
- data/bin/run_old_rspec +20 -0
- data/bin/run_rspec +24 -0
- data/bin/run_rspec_subset +38 -0
- data/bin/run_slow_rspec +20 -0
- data/blogs/R-on-Rails-Planning-Document.md +940 -0
- data/blogs/README.md +100 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +38 -66
- data/blogs/galaaz_ggplot/galaaz_ggplot.log +754 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot.md +115 -155
- data/blogs/galaaz_ggplot/galaaz_ggplot.tex +607 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-gfm/midwest_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-gfm/scatter_plot_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/midwest_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/scatter_plot_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/midwest_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/scatter_plot_rb.png +0 -0
- data/blogs/galaaz_ggplot/midwest.Rmd +3 -3
- data/blogs/galaaz_ggplot/midwest_external_png +0 -0
- data/blogs/gknit/gknit.Rmd +47 -52
- data/blogs/gknit/gknit.md +1430 -0
- data/blogs/gknit/gknit_files/figure-gfm/bubble-1.png +0 -0
- data/blogs/gknit/gknit_files/figure-gfm/diverging_bar.png +0 -0
- data/blogs/gknit/gknit_files/figure-html/bubble-1.png +0 -0
- data/blogs/gknit/gknit_files/figure-html/diverging_bar.png +0 -0
- data/blogs/gknit/lst.rds +0 -0
- data/blogs/gknit/model.rb +1 -1
- data/blogs/gknit/stats.bib +0 -0
- data/blogs/manual/include_model_local_repro.Rmd +14 -0
- data/blogs/manual/include_model_local_repro.md +75 -0
- data/blogs/manual/lst.rds +0 -0
- data/blogs/manual/manual.Rmd +855 -239
- data/blogs/manual/manual.log +1786 -0
- data/blogs/manual/manual.md +1416 -667
- data/blogs/manual/manual.tex +1883 -1161
- data/blogs/manual/manual_files/figure-html/bubble-1.png +0 -0
- data/blogs/manual/manual_files/figure-html/diverging_bar.png +0 -0
- data/blogs/manual/manual_files/figure-latex/bubble-1.png +0 -0
- data/blogs/manual/model.rb +1 -1
- data/blogs/nse_dplyr/nse_dplyr.Rmd +84 -111
- data/blogs/nse_dplyr/nse_dplyr.log +928 -0
- data/blogs/nse_dplyr/nse_dplyr.md +198 -229
- data/blogs/oh_my/not_so.rb +0 -0
- data/blogs/oh_my/oh_my.Rmd +1234 -25
- data/blogs/oh_my/oh_my.log +804 -0
- data/blogs/oh_my/oh_my.md +1663 -86
- data/blogs/oh_my/oh_my.tex +821 -0
- data/blogs/oh_my/old.Rmd +15 -14
- data/blogs/ruby_plot/ruby_plot.Rmd +58 -82
- data/blogs/ruby_plot/ruby_plot.log +885 -0
- data/blogs/ruby_plot/ruby_plot.md +71 -102
- data/blogs/ruby_plot/ruby_plot.tex +940 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/dose_len.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facet_by_delivery.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facet_by_dose.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_by_delivery_color.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_by_delivery_color2.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_with_points.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/final_box_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/final_violin_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/violin_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/dose_len.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
- data/blogs/test/test.Rmd +14 -0
- data/blogs/test/test.md +10 -0
- data/examples/50Plots_MasterList/Images/midwest-scatterplot.PNG +0 -0
- data/examples/50Plots_MasterList/ScatterPlot.rb +2 -1
- data/examples/50Plots_MasterList/scatter_plot.rb +1 -0
- data/examples/Bibliography/master.bib +0 -0
- data/examples/Bibliography/stats.bib +0 -0
- data/examples/R/calc.R +0 -0
- data/examples/R/java_interop.R +0 -0
- data/examples/bioconductor_deseq2_airway/Documentation/DESeq2-airway-walkthrough.md +56 -0
- data/examples/bioconductor_deseq2_airway/bench_galaaz_three_same_process.rb +54 -0
- data/examples/bioconductor_deseq2_airway/bench_r_three_same_process.R +34 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb +34 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz_optimized.rb +35 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_minimal.R +30 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_pipeline_for_bench.R +36 -0
- data/examples/islr/all.rb +14 -0
- data/examples/islr/ch2.spec.rb +38 -7
- data/examples/islr/ch3.spec.rb +12 -2
- data/examples/islr/ch3_boston.rb +28 -0
- data/examples/islr/ch3_multiple_regression.rb +1 -0
- data/examples/islr/ch6.spec.rb +25 -1
- data/examples/islr/x_y_rnorm.jpg +0 -0
- data/examples/latex_templates/Test-acm_article/acm_proc_article-sp.cls +0 -0
- data/examples/latex_templates/Test-acm_article/sigproc.bib +0 -0
- data/examples/latex_templates/Test-acs_article/acs-Test-acs_article.bib +0 -0
- data/examples/latex_templates/Test-acs_article/acs-my_output.bib +0 -0
- data/examples/latex_templates/Test-aea_article/BibFile.bib +0 -0
- data/examples/latex_templates/Test-aea_article/Test-aea_article.Rmd +0 -0
- data/examples/latex_templates/Test-aea_article/references.bib +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.Rmd +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.pdfsync +0 -0
- data/examples/latex_templates/Test-ieee_article/IEEEtran.bst +0 -0
- data/examples/latex_templates/Test-ieee_article/mybibfile.bib +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJournal.sty +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJreferences.bib +0 -0
- data/examples/latex_templates/Test-rjournal_article/Test-rjournal_article.Rmd +0 -0
- data/examples/misc/baseball.csv +0 -0
- data/examples/misc/ggplot.rb +5 -3
- data/examples/misc/moneyball.rb +1 -0
- data/examples/misc/subsetting.rb +1 -0
- data/examples/multithread_shards_to_r/shards_to_r.rb +68 -0
- data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/attend-grade-relationships.csv +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.Rmd +0 -0
- data/examples/rmarkdown/svm-xaringan-example/svm-xaringan-example.Rmd +0 -0
- data/examples/sthda_ggplot/README.md +0 -0
- data/examples/sthda_ggplot/RUN.md +41 -0
- data/examples/sthda_ggplot/all.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/density_gg.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_area.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_density.rb +3 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_dotplot.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_freqpoly.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_histogram.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/histogram_density.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/stat.rb +1 -0
- data/examples/sthda_ggplot/one_variable_discrete/bar.rb +1 -0
- data/examples/sthda_ggplot/qplots/box_violin_dot.rb +1 -0
- data/examples/sthda_ggplot/qplots/scatter_plots.rb +1 -0
- data/examples/sthda_ggplot/scatter_gg.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_bin2d.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_density2d.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_hex.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/geom_point.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/geom_smooth.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/misc.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_function/geom_area.rb +5 -3
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_bar.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_boxplot.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_dotplot.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_jitter.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_line.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_violin.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_disc/geom_jitter.rb +1 -0
- data/examples/sthda_ggplot/two_variables_error/geom_crossbar.rb +1 -0
- data/ext/new_bridge/Makefile +46 -0
- data/ext/new_bridge/galaaz_gatekeeper_phase0.cpp +12 -0
- data/ext/new_bridge/galaaz_gatekeeper_phase1.cpp +1639 -0
- data/lib/R_interface/galaaz_device.R +20 -0
- data/lib/R_interface/include_engine.R +109 -0
- data/lib/R_interface/new_bridge_adapter.rb +824 -0
- data/lib/R_interface/r.rb +177 -25
- data/lib/R_interface/r_arrow.rb +113 -0
- data/lib/R_interface/r_libs.R +3 -3
- data/lib/R_interface/r_methods.rb +13 -126
- data/lib/R_interface/r_module_s.rb +0 -0
- data/lib/R_interface/rbinary_operators.rb +20 -2
- data/lib/R_interface/rclosure.rb +5 -1
- data/lib/R_interface/rdata_frame.rb +34 -70
- data/lib/R_interface/rdevice.rb +125 -0
- data/lib/R_interface/rdevices.R +0 -0
- data/lib/R_interface/renvironment.rb +10 -4
- data/lib/R_interface/rexpression.rb +5 -1
- data/lib/R_interface/rindexed_object.rb +41 -13
- data/lib/R_interface/rlanguage.rb +20 -62
- data/lib/R_interface/rlist.rb +115 -25
- data/lib/R_interface/rlogical_operators.rb +0 -0
- data/lib/R_interface/rmatrix.rb +2 -11
- data/lib/R_interface/rmd_indexed_object.rb +5 -1
- data/lib/R_interface/robject.rb +348 -290
- data/lib/R_interface/rpkg.rb +0 -0
- data/lib/R_interface/rsupport.rb +609 -328
- data/lib/R_interface/rsupport_scope.rb +2 -1
- data/lib/R_interface/rsymbol.rb +50 -0
- data/lib/R_interface/ruby_callback.rb +2 -3
- data/lib/R_interface/ruby_extensions.rb +225 -175
- data/lib/R_interface/runary_operators.rb +0 -0
- data/lib/R_interface/rvector.rb +162 -31
- data/lib/galaaz.rb +0 -0
- data/lib/galaaz_jruby.rb +22 -0
- data/lib/galaaz_ruby.rb +34 -0
- data/lib/gknit/diagnostics.rb +50 -0
- data/lib/gknit/draft.rb +23 -17
- data/lib/gknit/include_engine.rb +15 -7
- data/lib/gknit/knitr_engine.rb +223 -74
- data/lib/gknit/rb_engine.rb +3 -3
- data/lib/gknit/ruby_engine.rb +0 -0
- data/lib/gknit.rb +1 -0
- data/lib/new_bridge/bootstrap/windows_bootstrap.rb +285 -0
- data/lib/new_bridge/envelope.rb +51 -0
- data/lib/new_bridge/eval_result.rb +26 -0
- data/lib/new_bridge/framing.rb +39 -0
- data/lib/new_bridge/instance_pool_client.rb +38 -0
- data/lib/new_bridge/r_instance_manager.rb +404 -0
- data/lib/new_bridge/session_client.rb +530 -0
- data/lib/new_bridge/tcp_framed.rb +44 -0
- data/lib/new_bridge.rb +9 -0
- data/lib/util/exec_ruby.rb +95 -20
- data/lib/util/inline_file.rb +35 -30
- data/new_bridge_specs/benchmark_phase5_5_unboxing_spec.rb +96 -0
- data/new_bridge_specs/eval_r_async_spec.rb +113 -0
- data/new_bridge_specs/integration_phase5_1_concurrent_spec.rb +50 -0
- data/new_bridge_specs/integration_phase5_1_eval_spec.rb +16 -0
- data/new_bridge_specs/integration_phase5_1_r_api_spec.rb +25 -0
- data/new_bridge_specs/integration_phase5_1_smoke_spec.rb +31 -0
- data/new_bridge_specs/integration_phase5_2_dataframe_unboxing_spec.rb +19 -0
- data/new_bridge_specs/integration_phase5_2_handle_eval_unboxing_spec.rb +25 -0
- data/new_bridge_specs/integration_phase5_3_callback_args_spec.rb +28 -0
- data/new_bridge_specs/integration_phase5_3_callback_error_spec.rb +22 -0
- data/new_bridge_specs/integration_phase5_3_callback_timeout_spec.rb +28 -0
- data/new_bridge_specs/integration_phase5_3_callbacks_smoke_spec.rb +22 -0
- data/new_bridge_specs/integration_phase5_3_edge_cases_spec.rb +52 -0
- data/new_bridge_specs/integration_phase5_3_nested_spec.rb +30 -0
- data/new_bridge_specs/integration_phase5_4_concurrent_sessions_spec.rb +53 -0
- data/new_bridge_specs/integration_phase5_4_nested_session_callbacks_spec.rb +49 -0
- data/new_bridge_specs/integration_phase5_4_session_routing_spec.rb +38 -0
- data/new_bridge_specs/integration_phase5_5_stress_concurrency_spec.rb +52 -0
- data/new_bridge_specs/integration_phase5_5_unbox_walk_spec.rb +46 -0
- data/new_bridge_specs/phase0_protocol_spec.rb +96 -0
- data/new_bridge_specs/phase1_req_ret_spec.rb +66 -0
- data/new_bridge_specs/phase2_multi_instance_spec.rb +67 -0
- data/new_bridge_specs/phase3_callbacks_spec.rb +71 -0
- data/new_bridge_specs/phase4_2_hardening_spec.rb +252 -0
- data/new_bridge_specs/phase4_3_r_instance_manager_spec.rb +85 -0
- data/new_bridge_specs/phase4_nested_callbacks_spec.rb +123 -0
- data/r_requires/ggplot.rb +0 -0
- data/r_requires/knitr.rb +0 -0
- data/specs/all.rb +15 -11
- data/specs/arrow_from_ruby_batches_spec.rb +50 -0
- data/specs/arrow_semantics_spec.rb +64 -0
- data/specs/bridge_concurrent_spec.rb +46 -0
- data/specs/bridge_nested_spec.rb +25 -0
- data/specs/dataframe_semantics_spec.rb +122 -0
- data/specs/dataframe_single_index_logical_filter_spec.rb +21 -0
- data/specs/dispatch_probe_cache_spec.rb +38 -0
- data/specs/dispatch_probe_error_class_fallback_spec.rb +20 -0
- data/specs/dispatch_probe_fallback_spec.rb +18 -0
- data/specs/environment_semantics_spec.rb +89 -0
- data/specs/field_access_spec.rb +31 -0
- data/specs/figures/bg.jpeg +0 -0
- data/specs/figures/bg.png +0 -0
- data/specs/figures/bg.svg +168 -57
- data/specs/figures/dose_len.png +0 -0
- data/specs/figures/no_args.jpeg +0 -0
- data/specs/figures/no_args.png +0 -0
- data/specs/figures/no_args.svg +168 -57
- data/specs/figures/width_height.jpeg +0 -0
- data/specs/figures/width_height.png +0 -0
- data/specs/figures/width_height_units1.jpeg +0 -0
- data/specs/figures/width_height_units1.png +0 -0
- data/specs/figures/width_height_units2.jpeg +0 -0
- data/specs/figures/width_height_units2.png +0 -0
- data/specs/formula_semantics_spec.rb +81 -0
- data/specs/galaaz_util_exec_ruby_spec.rb +85 -0
- data/specs/galaaz_util_inline_file_spec.rb +54 -0
- data/specs/gknit_cli_option_permutation_spec.rb +24 -0
- data/specs/gknit_include_engine_spec.rb +72 -0
- data/specs/gknit_install_timeout_report_spec.rb +69 -0
- data/specs/gknit_internal_error_report_spec.rb +57 -0
- data/specs/gknit_vector_map_output_spec.rb +59 -0
- data/specs/globalenv_guardrail_spec.rb +52 -0
- data/specs/language_expression_semantics_spec.rb +145 -0
- data/specs/list_semantics_spec.rb +111 -0
- data/specs/new_bridge_bulk_dataframe_transfer_spec.rb +44 -0
- data/specs/new_bridge_bulk_vector_transfer_spec.rb +73 -0
- data/specs/new_bridge_callback_timeout_spec.rb +69 -0
- data/specs/new_bridge_eval_r_fallback_spec.rb +55 -0
- data/specs/nil_null_spec.rb +42 -0
- data/specs/object_build_phase2_spec.rb +53 -0
- data/specs/phase1_callback_bridge_spec.rb +84 -0
- data/specs/phase2_gknit_generic_rendering_guardrail_spec.rb +46 -0
- data/specs/phase2_gknit_no_raw_code_leakage_spec.rb +43 -0
- data/specs/phase3_gknit_generic_graphics_capture_spec.rb +71 -0
- data/specs/plot_device_semantics_spec.rb +28 -0
- data/specs/plot_snapshot_semantics_spec.rb +58 -0
- data/specs/protocol_result_spec.rb +236 -0
- data/specs/r_batch_fail_fast_spec.rb +47 -0
- data/specs/r_bridge_bootstrap_spec.rb +11 -0
- data/specs/r_devices.spec.rb +1 -1
- data/specs/r_eval.spec.rb +16 -18
- data/specs/r_function.spec.rb +1 -1
- data/specs/r_instance_manager_spec.rb +285 -0
- data/specs/r_list_apply.spec.rb +15 -15
- data/specs/r_matrix.spec.rb +0 -0
- data/specs/r_nse.spec.rb +5 -5
- data/specs/r_object_send_dispatch_spec.rb +13 -0
- data/specs/r_vector_comparator_spec.rb +8 -0
- data/specs/r_vector_creation.spec.rb +0 -0
- data/specs/r_vector_functions.spec.rb +0 -0
- data/specs/r_vector_object.spec.rb +0 -0
- data/specs/r_vector_operators.spec.rb +0 -0
- data/specs/r_vector_structured_scalar_reads_spec.rb +35 -0
- data/specs/r_vector_subsetting.spec.rb +0 -0
- data/specs/range_helper_spec.rb +21 -0
- data/specs/rsupport_scope_spec.rb +28 -0
- data/specs/rsupport_var_name_thread_safety_spec.rb +24 -0
- data/specs/scalar_character_spec.rb +44 -0
- data/specs/scoped_symbol_dsl_refinement_spec.rb +40 -0
- data/specs/session_env_bridge_spec.rb +25 -0
- data/specs/simplecov_bootstrap_spec.rb +10 -0
- data/specs/spec_helper.rb +10 -0
- data/specs/tmp.rb +0 -0
- data/specs/unboxing_recursion_regression_spec.rb +30 -0
- data/specs/unboxing_spec.rb +49 -0
- data/specs/verify_callbacks.rb +42 -0
- data/sty/galaaz.sty +0 -0
- data/version.rb +1 -1
- metadata +219 -63
- data/blogs/galaaz_ggplot/galaaz_ggplot.html +0 -520
- data/blogs/galaaz_ggplot/galaaz_ggplot.pdf +0 -0
- data/blogs/galaaz_ggplot/midwest.html +0 -188
- data/blogs/gknit/gknit.html +0 -2266
- data/blogs/gknit/gknit.pdf +0 -0
- data/blogs/manual/manual.html +0 -4638
- data/blogs/manual/manual.pdf +0 -0
- data/blogs/manual/manual_files/figure-latex/diverging_bar.pdf +0 -0
- data/blogs/nse_dplyr/nse_dplyr.html +0 -878
- data/blogs/nse_dplyr/nse_dplyr.pdf +0 -0
- data/blogs/oh_my/oh_my.html +0 -568
- data/blogs/ruby_plot/ruby_plot.html +0 -544
- data/blogs/ruby_plot/ruby_plot.pdf +0 -0
- data/examples/latex_templates/Test-acs_article/Test-acs_article.pdf +0 -0
- data/examples/latex_templates/Test-aea_article/Test-aea_article.pdf +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.pdf +0 -0
- data/examples/latex_templates/Test-amq_article/pics/Figure2.pdf +0 -0
- data/examples/latex_templates/Test-asa_article/Test-asa_article.pdf +0 -0
- data/examples/latex_templates/Test-ieee_article/Test-ieee_article.pdf +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJwrapper.pdf +0 -0
- data/examples/latex_templates/Test-springer_article/Test-springer_article.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.pdf +0 -0
- data/specs/r_dataframe.spec.rb +0 -379
- data/specs/r_environment.spec.rb +0 -140
- data/specs/r_formula.spec.rb +0 -232
- data/specs/r_language.spec.rb +0 -112
- data/specs/r_list.spec.rb +0 -293
- data/specs/r_plots.spec.rb +0 -72
- data/specs/ruby_expression.spec.rb +0 -316
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'stringio'
|
|
4
|
+
require 'galaaz'
|
|
5
|
+
require_relative '../lib/new_bridge/r_instance_manager'
|
|
6
|
+
|
|
7
|
+
module NewBridge
|
|
8
|
+
class StubSessionClient
|
|
9
|
+
attr_reader :source_path, :host, :bridge_host, :r_cmd, :runtime_source_path, :start_calls
|
|
10
|
+
attr_accessor :eval_proc, :stopped
|
|
11
|
+
|
|
12
|
+
@@instances = []
|
|
13
|
+
@@start_errors = []
|
|
14
|
+
|
|
15
|
+
def self.instances
|
|
16
|
+
@@instances
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.reset!
|
|
20
|
+
@@instances = []
|
|
21
|
+
@@start_errors = []
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.enqueue_start_error(error)
|
|
25
|
+
@@start_errors << error
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initialize(source_path:, host:, r_cmd:, runtime_source_path: nil, bridge_host: nil)
|
|
29
|
+
@source_path = source_path
|
|
30
|
+
@host = host
|
|
31
|
+
@bridge_host = bridge_host
|
|
32
|
+
@r_cmd = r_cmd
|
|
33
|
+
@runtime_source_path = runtime_source_path
|
|
34
|
+
@start_calls = []
|
|
35
|
+
@stopped = false
|
|
36
|
+
@eval_proc = ->(_code, _kwargs) { 'ok' }
|
|
37
|
+
@@instances << self
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def start(accept_timeout: nil)
|
|
41
|
+
@start_calls << accept_timeout
|
|
42
|
+
raise @@start_errors.shift unless @@start_errors.empty?
|
|
43
|
+
true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def stop
|
|
47
|
+
@stopped = true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def eval_r(code = nil, **kwargs)
|
|
51
|
+
@eval_proc.call(code, kwargs)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe NewBridge::RInstanceManager do
|
|
57
|
+
let(:out) { StringIO.new }
|
|
58
|
+
let(:mgr) do
|
|
59
|
+
described_class.new(
|
|
60
|
+
source_path: File.expand_path('../ext/new_bridge/gatekeeper.cpp', __dir__),
|
|
61
|
+
session_client_class: NewBridge::StubSessionClient,
|
|
62
|
+
out: out,
|
|
63
|
+
docker_access_checker: -> { [true, nil] }
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
before do
|
|
68
|
+
NewBridge::StubSessionClient.reset!
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'spawns local instances and tracks metadata/default' do
|
|
72
|
+
mgr.spawn_local(instance_id: 'a', r_cmd: 'R', version: 'v1')
|
|
73
|
+
mgr.spawn_local(instance_id: 'b', r_cmd: '/usr/bin/R', version: 'v2')
|
|
74
|
+
|
|
75
|
+
expect(mgr.default_instance_id).to eq('a')
|
|
76
|
+
ids = mgr.instance_ids
|
|
77
|
+
expect(ids).to include('a', 'b')
|
|
78
|
+
|
|
79
|
+
info = mgr.instances
|
|
80
|
+
expect(info.size).to eq(2)
|
|
81
|
+
expect(info.find { |h| h[:id] == 'a' }[:default]).to eq(true)
|
|
82
|
+
expect(info.find { |h| h[:id] == 'b' }[:runtime]).to eq('local')
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'raises on duplicate local instance id' do
|
|
86
|
+
mgr.spawn_local(instance_id: 'a', version: 'v1')
|
|
87
|
+
expect { mgr.spawn_local(instance_id: 'a', version: 'v1') }.to raise_error(ArgumentError, /already exists/)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'supports spawn runtime dispatch and container metadata' do
|
|
91
|
+
mgr.spawn(instance_id: 'c1', runtime: 'container', version: 'v-current', image: 'r-image', bridge_hosts: ['host.docker.internal'])
|
|
92
|
+
|
|
93
|
+
item = mgr.instances.find { |h| h[:id] == 'c1' }
|
|
94
|
+
expect(item[:runtime]).to eq('container')
|
|
95
|
+
expect(item[:provider]).to eq('docker')
|
|
96
|
+
expect(item[:image]).to eq('r-image')
|
|
97
|
+
expect(item[:container_name]).to include('galaaz-c1')
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'supports local runtime via unified spawn API' do
|
|
101
|
+
mgr.spawn(instance_id: 'l1', runtime: 'local', version: 'v-local', r_cmd: 'R')
|
|
102
|
+
expect(mgr.instance_ids).to include('l1')
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'rejects invalid runtime values and missing container image' do
|
|
106
|
+
expect do
|
|
107
|
+
mgr.spawn(instance_id: 'x', runtime: 'unknown', version: 'v')
|
|
108
|
+
end.to raise_error(ArgumentError, /unsupported runtime/)
|
|
109
|
+
|
|
110
|
+
expect do
|
|
111
|
+
mgr.spawn(instance_id: 'x', runtime: 'container', version: 'v', image: '')
|
|
112
|
+
end.to raise_error(ArgumentError, /image is required/)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'retries once on infrastructure timeout by restarting instance' do
|
|
116
|
+
mgr.spawn_local(instance_id: 'a', version: 'v1')
|
|
117
|
+
first = NewBridge::StubSessionClient.instances.first
|
|
118
|
+
first.eval_proc = ->(_code, _kwargs) { raise Timeout::Error, 'timeout' }
|
|
119
|
+
|
|
120
|
+
result = mgr.eval_r('1+1', session_id: 's1', instance_id: 'a')
|
|
121
|
+
expect(result).to eq('ok')
|
|
122
|
+
expect(NewBridge::StubSessionClient.instances.size).to eq(2)
|
|
123
|
+
expect(first.stopped).to eq(true)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'routes by version and evaluates once per version' do
|
|
127
|
+
mgr.spawn_local(instance_id: 'a', version: 'v1')
|
|
128
|
+
mgr.spawn_local(instance_id: 'b', version: 'v1')
|
|
129
|
+
mgr.spawn_local(instance_id: 'c', version: 'v2')
|
|
130
|
+
|
|
131
|
+
expect(mgr.eval_with_version('2+2', version: 'v2')).to eq('ok')
|
|
132
|
+
expect { mgr.eval_with_version('2+2', version: 'missing') }.to raise_error(KeyError)
|
|
133
|
+
|
|
134
|
+
out = mgr.eval_all_versions('2+2')
|
|
135
|
+
expect(out.keys.sort).to eq(%w[v1 v2])
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'supports default switching and stop variants' do
|
|
139
|
+
mgr.spawn_local(instance_id: 'a', version: 'v1')
|
|
140
|
+
mgr.spawn_local(instance_id: 'b', version: 'v2')
|
|
141
|
+
mgr.set_default_instance('b')
|
|
142
|
+
expect(mgr.default_instance_id).to eq('b')
|
|
143
|
+
expect { mgr.set_default_instance('missing') }.to raise_error(KeyError)
|
|
144
|
+
|
|
145
|
+
mgr.stop_all(keep_default: true)
|
|
146
|
+
expect(mgr.instance_ids).to eq(['b'])
|
|
147
|
+
|
|
148
|
+
mgr.stop('b')
|
|
149
|
+
expect(mgr.instance_ids).to eq([])
|
|
150
|
+
expect(mgr.default_instance_id).to eq(nil)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it 'supports force killing container instances' do
|
|
154
|
+
mgr.spawn(instance_id: 'c1', runtime: 'container', version: 'v-current', image: 'r-image', bridge_hosts: ['host.docker.internal'])
|
|
155
|
+
expect { mgr.kill_container('c1') }.not_to raise_error
|
|
156
|
+
|
|
157
|
+
mgr.spawn_local(instance_id: 'a', version: 'v1')
|
|
158
|
+
expect { mgr.kill_container('a') }.to raise_error(ArgumentError, /not container runtime/)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it 'fails container spawn when docker checker reports inaccessible daemon' do
|
|
162
|
+
bad_mgr = described_class.new(
|
|
163
|
+
source_path: File.expand_path('../ext/new_bridge/gatekeeper.cpp', __dir__),
|
|
164
|
+
session_client_class: NewBridge::StubSessionClient,
|
|
165
|
+
out: out,
|
|
166
|
+
docker_access_checker: -> { [false, 'permission denied'] }
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
expect do
|
|
170
|
+
bad_mgr.spawn(instance_id: 'c2', runtime: 'container', version: 'v', image: 'img')
|
|
171
|
+
end.to raise_error(NewBridge::RInstanceManager::Error, /docker daemon is not accessible: permission denied/)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it 'tries multiple bridge hosts and logs failures before succeeding' do
|
|
175
|
+
NewBridge::StubSessionClient.enqueue_start_error(StandardError.new('accept failed'))
|
|
176
|
+
mgr.spawn(
|
|
177
|
+
instance_id: 'c-fallback',
|
|
178
|
+
runtime: 'container',
|
|
179
|
+
version: 'v',
|
|
180
|
+
image: 'img',
|
|
181
|
+
bridge_hosts: %w[bad.host good.host]
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
text = out.string
|
|
185
|
+
expect(text).to include('trying bridge host bad.host')
|
|
186
|
+
expect(text).to include('trying bridge host good.host')
|
|
187
|
+
expect(text).to include('bridge host bad.host failed')
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it 'raises when all bridge host candidates fail' do
|
|
191
|
+
NewBridge::StubSessionClient.enqueue_start_error(StandardError.new('fail 1'))
|
|
192
|
+
NewBridge::StubSessionClient.enqueue_start_error(StandardError.new('fail 2'))
|
|
193
|
+
|
|
194
|
+
expect do
|
|
195
|
+
mgr.spawn(
|
|
196
|
+
instance_id: 'c-fail',
|
|
197
|
+
runtime: 'container',
|
|
198
|
+
version: 'v',
|
|
199
|
+
image: 'img',
|
|
200
|
+
bridge_hosts: %w[h1 h2]
|
|
201
|
+
)
|
|
202
|
+
end.to raise_error(NewBridge::RInstanceManager::Error, /container runtime start failed/)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it 'classifies retryable infrastructure errors conservatively' do
|
|
206
|
+
expect(mgr.send(:infrastructure_retryable_error?, Timeout::Error.new('t'))).to eq(true)
|
|
207
|
+
expect(mgr.send(:infrastructure_retryable_error?, IOError.new('io'))).to eq(true)
|
|
208
|
+
expect(mgr.send(:infrastructure_retryable_error?, NewBridge::SessionClient::TimeoutError.new('timeout'))).to eq(true)
|
|
209
|
+
expect(mgr.send(:infrastructure_retryable_error?, NewBridge::SessionClient::RProcessError.new('connection closed by peer'))).to eq(true)
|
|
210
|
+
expect(mgr.send(:infrastructure_retryable_error?, NewBridge::SessionClient::RProcessError.new('evaluation error: bad call'))).to eq(false)
|
|
211
|
+
expect(mgr.send(:infrastructure_retryable_error?, StandardError.new('other'))).to eq(false)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it 'builds bridge host candidates honoring preferred host cache' do
|
|
215
|
+
mgr.instance_variable_set(:@preferred_bridge_host, 'cached.host')
|
|
216
|
+
allow(mgr).to receive(:running_in_wsl?).and_return(false)
|
|
217
|
+
allow(mgr).to receive(:local_wsl_ip).and_return('172.22.0.5')
|
|
218
|
+
|
|
219
|
+
with_cache = mgr.send(:bridge_host_candidates, relearn: false)
|
|
220
|
+
relearn = mgr.send(:bridge_host_candidates, relearn: true)
|
|
221
|
+
|
|
222
|
+
expect(with_cache.first).to eq('cached.host')
|
|
223
|
+
expect(with_cache).to include('host.docker.internal', '172.22.0.5')
|
|
224
|
+
expect(relearn).to eq(%w[host.docker.internal 172.22.0.5])
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it 'prefers WSL IP before host.docker.internal when running in WSL' do
|
|
228
|
+
allow(mgr).to receive(:running_in_wsl?).and_return(true)
|
|
229
|
+
allow(mgr).to receive(:local_wsl_ip).and_return('172.22.0.5')
|
|
230
|
+
|
|
231
|
+
expect(mgr.send(:bridge_host_candidates, relearn: true)).to eq(%w[172.22.0.5 host.docker.internal])
|
|
232
|
+
|
|
233
|
+
mgr.instance_variable_set(:@preferred_bridge_host, 'cached.host')
|
|
234
|
+
with_cache = mgr.send(:bridge_host_candidates, relearn: false)
|
|
235
|
+
expect(with_cache.first).to eq('cached.host')
|
|
236
|
+
expect(with_cache).to eq(%w[cached.host 172.22.0.5 host.docker.internal])
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it 'handles docker log and cleanup helper branches' do
|
|
240
|
+
allow(Open3).to receive(:capture3).with('docker', 'logs', '--tail', '80', 'cname').and_return(['ok logs', '', instance_double(Process::Status, success?: true)])
|
|
241
|
+
expect(mgr.send(:docker_logs, 'cname')).to eq('ok logs')
|
|
242
|
+
|
|
243
|
+
allow(Open3).to receive(:capture3).with('docker', 'logs', '--tail', '80', 'cname2').and_return(['', 'no logs', instance_double(Process::Status, success?: false)])
|
|
244
|
+
expect(mgr.send(:docker_logs, 'cname2')).to eq('no logs')
|
|
245
|
+
|
|
246
|
+
allow(Open3).to receive(:capture3).with('docker', 'rm', '-f', 'dead-c').and_return(['', '', instance_double(Process::Status, success?: true)])
|
|
247
|
+
expect { mgr.send(:cleanup_container, { runtime: 'container', container_name: 'dead-c' }, force: true) }.not_to raise_error
|
|
248
|
+
expect { mgr.send(:cleanup_container, { runtime: 'container', container_name: '' }, force: true) }.not_to raise_error
|
|
249
|
+
expect { mgr.send(:cleanup_container, { runtime: 'local' }, force: true) }.not_to raise_error
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it 'reads local wsl ip and handles shell failures' do
|
|
253
|
+
allow(Open3).to receive(:capture3).with('bash', '-lc', "hostname -I | awk '{print $1}'").and_return(["172.22.0.7\n", '', instance_double(Process::Status, success?: true)])
|
|
254
|
+
expect(mgr.send(:local_wsl_ip)).to eq('172.22.0.7')
|
|
255
|
+
|
|
256
|
+
allow(Open3).to receive(:capture3).with('bash', '-lc', "hostname -I | awk '{print $1}'").and_return(['', 'err', instance_double(Process::Status, success?: false)])
|
|
257
|
+
expect(mgr.send(:local_wsl_ip)).to eq(nil)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it 'checks docker daemon access when checker is not provided' do
|
|
261
|
+
mgr2 = described_class.new(
|
|
262
|
+
source_path: File.expand_path('../ext/new_bridge/gatekeeper.cpp', __dir__),
|
|
263
|
+
session_client_class: NewBridge::StubSessionClient,
|
|
264
|
+
out: out
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
allow(Open3).to receive(:capture3).with('docker', 'info').and_return(['ok', '', instance_double(Process::Status, success?: true)])
|
|
268
|
+
expect { mgr2.send(:ensure_docker_daemon_access!) }.not_to raise_error
|
|
269
|
+
|
|
270
|
+
allow(Open3).to receive(:capture3).with('docker', 'info').and_return(['', 'permission denied', instance_double(Process::Status, success?: false)])
|
|
271
|
+
expect { mgr2.send(:ensure_docker_daemon_access!) }.to raise_error(NewBridge::RInstanceManager::Error, /docker daemon is not accessible: permission denied/)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it 'handles helper rescues for docker logs, cleanup, and local ip' do
|
|
275
|
+
allow(Open3).to receive(:capture3).with('docker', 'logs', '--tail', '80', 'boom').and_raise(StandardError, 'x')
|
|
276
|
+
expect(mgr.send(:docker_logs, 'boom')).to eq('')
|
|
277
|
+
|
|
278
|
+
allow(Open3).to receive(:capture3).with('docker', 'rm', '-f', 'boom').and_raise(StandardError, 'x')
|
|
279
|
+
expect { mgr.send(:cleanup_container, { runtime: 'container', container_name: 'boom' }, force: true) }.not_to raise_error
|
|
280
|
+
|
|
281
|
+
allow(Open3).to receive(:capture3).with('bash', '-lc', "hostname -I | awk '{print $1}'").and_raise(StandardError, 'x')
|
|
282
|
+
expect(mgr.send(:local_wsl_ip)).to eq(nil)
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
data/specs/r_list_apply.spec.rb
CHANGED
|
@@ -32,7 +32,7 @@ describe R::List do
|
|
|
32
32
|
@x = R.list(a: (1..10), beta: R.exp(-3..3), logic: R.c(true, false, false, true))
|
|
33
33
|
R.library("stats")
|
|
34
34
|
# Make @q the function R quantile
|
|
35
|
-
@q =
|
|
35
|
+
@q = ~R[:quantile]
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
it "should work with lapply and mean" do
|
|
@@ -49,7 +49,7 @@ describe R::List do
|
|
|
49
49
|
# and method all__equal is not defined on floats.
|
|
50
50
|
expect(R.all__equal(mean.beta,
|
|
51
51
|
4.5351252347,
|
|
52
|
-
tolerance: (
|
|
52
|
+
tolerance: (~R[:".Machine"]).double__eps ** 0.5)).to eq true
|
|
53
53
|
|
|
54
54
|
expect(mean.logic).to eq 0.5
|
|
55
55
|
end
|
|
@@ -62,21 +62,21 @@ describe R::List do
|
|
|
62
62
|
expect(quant.a[1]).to eq R.c('0%': 1.0)
|
|
63
63
|
expect(quant.a[[1]]).to eq 1.0
|
|
64
64
|
|
|
65
|
-
expect(quant.a[['50
|
|
66
|
-
expect(quant.a['50
|
|
67
|
-
expect(R.all__equal(quant.beta['100
|
|
68
|
-
R.c('100
|
|
69
|
-
tolerance: (
|
|
65
|
+
expect(quant.a[['50%']]).to eq 5.50
|
|
66
|
+
expect(quant.a['50%']).to eq R.c('50%': 5.50)
|
|
67
|
+
expect(R.all__equal(quant.beta['100%'],
|
|
68
|
+
R.c('100%': 20.08553692),
|
|
69
|
+
tolerance: (~R[:".Machine"]).double__eps ** 0.5)).to eq true
|
|
70
70
|
expect(quant.logic[[2]]).to eq 0.0
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
it "should allow using method lapply with quantile" do
|
|
74
74
|
x = R.lapply(@x, @q, R.c(0.25, 0.50, 0.75))
|
|
75
75
|
expect(x.a[[1]]).to eq 3.25
|
|
76
|
-
expect(x.a[['50
|
|
77
|
-
expect(R.all__equal(x.beta['75
|
|
78
|
-
R.c('75
|
|
79
|
-
tolerance: (
|
|
76
|
+
expect(x.a[['50%']]).to eq 5.50
|
|
77
|
+
expect(R.all__equal(x.beta['75%'],
|
|
78
|
+
R.c('75%': 5.0536690),
|
|
79
|
+
tolerance: (~R[:".Machine"]).double__eps ** 0.5)).to eq true
|
|
80
80
|
expect(x.logic[[2]]).to eq 0.5
|
|
81
81
|
end
|
|
82
82
|
|
|
@@ -84,9 +84,9 @@ describe R::List do
|
|
|
84
84
|
# sapply will return a matrix
|
|
85
85
|
quant = R.sapply(@x, @q)
|
|
86
86
|
expect(quant.rclass).to eq 'matrix'
|
|
87
|
-
expect(quant[:all, 'a']).to eq R.c('0%': 1, '25
|
|
88
|
-
'50
|
|
89
|
-
'100
|
|
87
|
+
expect(quant[:all, 'a']).to eq R.c('0%': 1, '25%': 3.25,
|
|
88
|
+
'50%': 5.50, '75%': 7.75,
|
|
89
|
+
'100%': 10)
|
|
90
90
|
|
|
91
91
|
expect(quant[3, 'beta']).to eq 1.0
|
|
92
92
|
end
|
|
@@ -97,7 +97,7 @@ describe R::List do
|
|
|
97
97
|
i39 = R.sapply((3..9), "seq")
|
|
98
98
|
expect(i39[[1]]).to eq R.c(1, 2, 3)
|
|
99
99
|
expect(i39[[7]]).to eq R.c(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
|
100
|
-
sap = R.sapply(i39,
|
|
100
|
+
sap = R.sapply(i39, ~R[:fivenum])
|
|
101
101
|
expect(sap[1, 1]).to eq 1.0
|
|
102
102
|
expect(sap[5, 7]).to eq 9.0
|
|
103
103
|
end
|
data/specs/r_matrix.spec.rb
CHANGED
|
File without changes
|
data/specs/r_nse.spec.rb
CHANGED
|
@@ -40,17 +40,17 @@ describe R do
|
|
|
40
40
|
df[r, :all]
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
puts subset(@sample_df, :a >= 4)
|
|
43
|
+
puts subset(@sample_df, R[:a] >= 4)
|
|
44
44
|
|
|
45
45
|
y = 4
|
|
46
46
|
x = 4
|
|
47
47
|
condition = 4
|
|
48
48
|
condition_call = 4
|
|
49
49
|
|
|
50
|
-
puts subset(@sample_df, :a == 4)
|
|
51
|
-
puts subset(@sample_df, :a == y)
|
|
52
|
-
puts subset(@sample_df, :a == condition)
|
|
53
|
-
puts subset(@sample_df, :a == condition_call)
|
|
50
|
+
puts subset(@sample_df, R[:a] == 4)
|
|
51
|
+
puts subset(@sample_df, R[:a] == y)
|
|
52
|
+
puts subset(@sample_df, R[:a] == condition)
|
|
53
|
+
puts subset(@sample_df, R[:a] == condition_call)
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'galaaz'
|
|
4
|
+
|
|
5
|
+
describe 'R::Object send dispatch' do
|
|
6
|
+
it 'uses Ruby send instead of R send(...) function call' do
|
|
7
|
+
df = R.data__frame(mpg: R.c(21, 22), cyl: R.c(6, 4))
|
|
8
|
+
mpg = df.send(:mpg)
|
|
9
|
+
|
|
10
|
+
expect(mpg).to be_a(R::Object)
|
|
11
|
+
expect(mpg.unboxed_get(0)).to eq(21)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'galaaz'
|
|
4
|
+
|
|
5
|
+
describe 'R::Vector structured scalar reads (result protocol)' do
|
|
6
|
+
it 'unboxes indexed integer element without relying on printed length/typeof' do
|
|
7
|
+
v = R.c(10, 20, 30)
|
|
8
|
+
expect(v.unboxed_get(1)).to eq(20)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'unboxes indexed double element' do
|
|
12
|
+
v = R.c(1.5, 2.5)
|
|
13
|
+
expect(v.unboxed_get(0)).to eq(1.5)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'unboxes logical TRUE, FALSE, and NA via scalar_logical envelope' do
|
|
17
|
+
v = R.c(true, false, R::NA)
|
|
18
|
+
expect(v.unboxed_get(0)).to eq(true)
|
|
19
|
+
expect(v.unboxed_get(1)).to eq(false)
|
|
20
|
+
expect(v.unboxed_get(2)).to be_nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'unboxes indexed character element' do
|
|
24
|
+
v = R.c('a', 'b')
|
|
25
|
+
expect(v.unboxed_get(1)).to eq('b')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'stitch uses protocol-based length' do
|
|
29
|
+
v = R.c(1.0, 2.0, 3.0)
|
|
30
|
+
out = v.stitch(halo: 0) { |chunk| chunk.map { |x| x * 2 } }
|
|
31
|
+
expect(out).to be_a(R::Vector)
|
|
32
|
+
expect(out.length.unboxed_get(0)).to eq(3)
|
|
33
|
+
expect((out >> nil)).to eq([2.0, 4.0, 6.0])
|
|
34
|
+
end
|
|
35
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'galaaz'
|
|
4
|
+
|
|
5
|
+
describe 'range_helper / up_to DSL' do
|
|
6
|
+
it 'supports select with symbol range syntax' do
|
|
7
|
+
ok = R::Support.eval("requireNamespace('dplyr', quietly=TRUE)")
|
|
8
|
+
skip 'dplyr is not available' unless ok == true
|
|
9
|
+
|
|
10
|
+
df = R.data__frame(
|
|
11
|
+
year: R.c(2020, 2021),
|
|
12
|
+
month: R.c(1, 2),
|
|
13
|
+
day: R.c(10, 11),
|
|
14
|
+
tailnum: R.c('N1', 'N2')
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
out = R.dplyr___select(df, R[:year].up_to(R[:day]))
|
|
18
|
+
cols = R.names(out) >> nil
|
|
19
|
+
expect(cols).to eq(%w[year month day])
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'galaaz'
|
|
4
|
+
|
|
5
|
+
describe R::Support do
|
|
6
|
+
describe '.new_scope' do
|
|
7
|
+
it 'evaluates expression-style calls inside dataframe scope' do
|
|
8
|
+
df = R.data__frame(a: (1..4), b: R.c(10, 20, 30, 40))
|
|
9
|
+
|
|
10
|
+
out = R::Support.new_scope(:with, df) do
|
|
11
|
+
(a > 2).eval(df)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
expect(out).to eq R.c(false, false, true, true)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'allows direct column access via generated methods' do
|
|
18
|
+
df = R.data__frame(a: (1..3), b: R.c(5, 6, 7))
|
|
19
|
+
|
|
20
|
+
val = R::Support.new_scope(:with, df) do
|
|
21
|
+
(a + b).eval(df)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
expect(val).to eq R.c(6, 8, 10)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'galaaz'
|
|
2
|
+
|
|
3
|
+
describe R::Support do
|
|
4
|
+
it 'generates unique g2_v handles under concurrency' do
|
|
5
|
+
n_threads = 8
|
|
6
|
+
per_thread = 200
|
|
7
|
+
names = []
|
|
8
|
+
lock = Mutex.new
|
|
9
|
+
|
|
10
|
+
threads = n_threads.times.map do
|
|
11
|
+
Thread.new do
|
|
12
|
+
local = []
|
|
13
|
+
per_thread.times { local << R::Support.generate_var_name }
|
|
14
|
+
lock.synchronize { names.concat(local) }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
threads.each(&:join)
|
|
19
|
+
|
|
20
|
+
expect(names.length).to eq(n_threads * per_thread)
|
|
21
|
+
expect(names.uniq.length).to eq(names.length)
|
|
22
|
+
expect(names).to all(match(/\Ag2_v\d+\z/))
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Scalar character result protocol: when R sends a length-1 character (type 3),
|
|
3
|
+
# the bridge unescapes so Ruby receives real newlines and double quotes
|
|
4
|
+
# (e.g. \n -> newline, \" -> ", \\ -> \). This avoids SyntaxError when chunk
|
|
5
|
+
# code is round-tripped (e.g. gknit exec_ruby).
|
|
6
|
+
# Run with: bin/run_rspec specs/scalar_character_spec.rb
|
|
7
|
+
|
|
8
|
+
require 'galaaz'
|
|
9
|
+
|
|
10
|
+
describe "Scalar character (result protocol unescaping)" do
|
|
11
|
+
|
|
12
|
+
context "R -> Ruby: literal \\n and \" in string" do
|
|
13
|
+
# R string "a\\nb" has chars: a, backslash, n, b. Bridge unescapes \n -> newline.
|
|
14
|
+
it "unescapes \\n to real newline when unboxing length-1 character" do
|
|
15
|
+
v = R::Support.eval('"a\\\\nb"')
|
|
16
|
+
expect(v).to be_a(R::Object)
|
|
17
|
+
s = v >> 0
|
|
18
|
+
expect(s).to eq "a\nb"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# R string "a\\\"b" has chars: a, backslash, double-quote, b. Bridge unescapes \" -> ".
|
|
22
|
+
it "unescapes \\\" to real double-quote when unboxing length-1 character" do
|
|
23
|
+
v = R::Support.eval('"a\\\\\\"b"')
|
|
24
|
+
expect(v).to be_a(R::Object)
|
|
25
|
+
s = v >> 0
|
|
26
|
+
expect(s).to eq 'a"b'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "unescapes both \\n and \\\" in one string" do
|
|
30
|
+
# R string with a, \n, b, \", c -> Ruby "a\nb\"c"
|
|
31
|
+
v = R::Support.eval('"a\\\\nb\\\\\\"c"')
|
|
32
|
+
expect(v).to be_a(R::Object)
|
|
33
|
+
s = v >> 0
|
|
34
|
+
expect(s).to eq "a\nb\"c"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context "plain strings unchanged" do
|
|
39
|
+
it "leaves strings without backslash escapes unchanged" do
|
|
40
|
+
v = R::Support.eval('"hello"')
|
|
41
|
+
expect((v >> 0)).to eq "hello"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'galaaz'
|
|
4
|
+
|
|
5
|
+
module ScopedSymbolDslWithUsing
|
|
6
|
+
using Galaaz::SymbolDSL
|
|
7
|
+
|
|
8
|
+
def self.build_expr
|
|
9
|
+
:a + :b + 5
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.fetch_symbol
|
|
13
|
+
~:letters
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
module ScopedSymbolDslWithoutUsing
|
|
18
|
+
def self.build_expr
|
|
19
|
+
:a + :b + 5
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe 'Scoped Symbol DSL refinement' do
|
|
24
|
+
it 'enables symbol expression DSL inside lexical using scope' do
|
|
25
|
+
expr = ScopedSymbolDslWithUsing.build_expr
|
|
26
|
+
expect(expr).to be_a(R::Language)
|
|
27
|
+
expect(expr.to_s).to eq('a + b + 5L')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'enables unary symbol fetch inside lexical using scope' do
|
|
31
|
+
vec = ScopedSymbolDslWithUsing.fetch_symbol
|
|
32
|
+
expect(vec).to be_a(R::Vector)
|
|
33
|
+
expect(vec[1]).to eq('a')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'does not enable symbol expression DSL outside using scope' do
|
|
37
|
+
expect { ScopedSymbolDslWithoutUsing.build_expr }.to raise_error(NoMethodError)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'galaaz'
|
|
4
|
+
|
|
5
|
+
describe 'Session env bridge helpers' do
|
|
6
|
+
it 'ensures, assigns, gets, and removes values in a session-scoped env' do
|
|
7
|
+
bridge = R.bridge
|
|
8
|
+
skip 'session env API available only on NewBridge adapter' unless bridge.respond_to?(:ensure_session_env)
|
|
9
|
+
|
|
10
|
+
sid = "spec_sid_#{Time.now.to_i}_#{rand(1000)}"
|
|
11
|
+
key = 'tmp_value'
|
|
12
|
+
|
|
13
|
+
expect(bridge.ensure_session_env(sid)).to eq(nil)
|
|
14
|
+
|
|
15
|
+
bridge.assign_session(sid, key, '42L')
|
|
16
|
+
got = bridge.get_session(sid, key)
|
|
17
|
+
expect(got['kind'].to_s).to eq('integer')
|
|
18
|
+
expect(got['value']).to eq(42)
|
|
19
|
+
|
|
20
|
+
bridge.rm_session(sid, key)
|
|
21
|
+
expect do
|
|
22
|
+
bridge.get_session(sid, key)
|
|
23
|
+
end.to raise_error(NewBridge::SessionClient::RProcessError)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
describe 'SimpleCov bootstrap' do
|
|
2
|
+
it 'loads SimpleCov when available' do
|
|
3
|
+
if Gem.loaded_specs.key?('simplecov')
|
|
4
|
+
expect(defined?(SimpleCov)).to eq('constant')
|
|
5
|
+
expect(SimpleCov.running).to eq(true)
|
|
6
|
+
else
|
|
7
|
+
skip('simplecov gem is not available in this environment')
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
data/specs/tmp.rb
CHANGED
|
File without changes
|