juniper-data 0.4.2__py3-none-any.whl

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.
Files changed (95) hide show
  1. juniper_data/__init__.py +88 -0
  2. juniper_data/__main__.py +78 -0
  3. juniper_data/api/__init__.py +10 -0
  4. juniper_data/api/app.py +111 -0
  5. juniper_data/api/middleware.py +95 -0
  6. juniper_data/api/routes/__init__.py +9 -0
  7. juniper_data/api/routes/datasets.py +414 -0
  8. juniper_data/api/routes/generators.py +125 -0
  9. juniper_data/api/routes/health.py +49 -0
  10. juniper_data/api/security.py +238 -0
  11. juniper_data/api/settings.py +109 -0
  12. juniper_data/core/__init__.py +32 -0
  13. juniper_data/core/artifacts.py +63 -0
  14. juniper_data/core/dataset_id.py +38 -0
  15. juniper_data/core/models.py +135 -0
  16. juniper_data/core/split.py +120 -0
  17. juniper_data/generators/__init__.py +15 -0
  18. juniper_data/generators/arc_agi/__init__.py +11 -0
  19. juniper_data/generators/arc_agi/generator.py +229 -0
  20. juniper_data/generators/arc_agi/params.py +56 -0
  21. juniper_data/generators/checkerboard/__init__.py +15 -0
  22. juniper_data/generators/checkerboard/generator.py +114 -0
  23. juniper_data/generators/checkerboard/params.py +32 -0
  24. juniper_data/generators/circles/__init__.py +11 -0
  25. juniper_data/generators/circles/generator.py +112 -0
  26. juniper_data/generators/circles/params.py +31 -0
  27. juniper_data/generators/csv_import/__init__.py +15 -0
  28. juniper_data/generators/csv_import/generator.py +198 -0
  29. juniper_data/generators/csv_import/params.py +48 -0
  30. juniper_data/generators/gaussian/__init__.py +11 -0
  31. juniper_data/generators/gaussian/generator.py +149 -0
  32. juniper_data/generators/gaussian/params.py +53 -0
  33. juniper_data/generators/mnist/__init__.py +11 -0
  34. juniper_data/generators/mnist/generator.py +124 -0
  35. juniper_data/generators/mnist/params.py +39 -0
  36. juniper_data/generators/spiral/__init__.py +57 -0
  37. juniper_data/generators/spiral/defaults.py +39 -0
  38. juniper_data/generators/spiral/generator.py +206 -0
  39. juniper_data/generators/spiral/params.py +148 -0
  40. juniper_data/generators/xor/__init__.py +11 -0
  41. juniper_data/generators/xor/generator.py +162 -0
  42. juniper_data/generators/xor/params.py +30 -0
  43. juniper_data/storage/__init__.py +120 -0
  44. juniper_data/storage/base.py +279 -0
  45. juniper_data/storage/cached.py +211 -0
  46. juniper_data/storage/hf_store.py +257 -0
  47. juniper_data/storage/kaggle_store.py +333 -0
  48. juniper_data/storage/local_fs.py +232 -0
  49. juniper_data/storage/memory.py +136 -0
  50. juniper_data/storage/postgres_store.py +373 -0
  51. juniper_data/storage/redis_store.py +264 -0
  52. juniper_data/tests/__init__.py +1 -0
  53. juniper_data/tests/conftest.py +68 -0
  54. juniper_data/tests/fixtures/generate_golden_datasets.py +199 -0
  55. juniper_data/tests/integration/__init__.py +1 -0
  56. juniper_data/tests/integration/test_api.py +283 -0
  57. juniper_data/tests/integration/test_e2e_workflow.py +378 -0
  58. juniper_data/tests/integration/test_lifecycle_api.py +304 -0
  59. juniper_data/tests/integration/test_security_integration.py +189 -0
  60. juniper_data/tests/integration/test_storage_workflow.py +259 -0
  61. juniper_data/tests/performance/__init__.py +1 -0
  62. juniper_data/tests/performance/test_generator_benchmarks.py +178 -0
  63. juniper_data/tests/performance/test_storage_benchmarks.py +257 -0
  64. juniper_data/tests/unit/__init__.py +1 -0
  65. juniper_data/tests/unit/test_api_app.py +206 -0
  66. juniper_data/tests/unit/test_api_routes.py +407 -0
  67. juniper_data/tests/unit/test_api_settings.py +100 -0
  68. juniper_data/tests/unit/test_arc_agi_generator.py +525 -0
  69. juniper_data/tests/unit/test_artifacts.py +145 -0
  70. juniper_data/tests/unit/test_cached_store.py +423 -0
  71. juniper_data/tests/unit/test_checkerboard_generator.py +232 -0
  72. juniper_data/tests/unit/test_circles_generator.py +256 -0
  73. juniper_data/tests/unit/test_csv_import_generator.py +345 -0
  74. juniper_data/tests/unit/test_dataset_id.py +181 -0
  75. juniper_data/tests/unit/test_gaussian_generator.py +333 -0
  76. juniper_data/tests/unit/test_hf_store.py +416 -0
  77. juniper_data/tests/unit/test_init.py +93 -0
  78. juniper_data/tests/unit/test_kaggle_store.py +469 -0
  79. juniper_data/tests/unit/test_lifecycle.py +394 -0
  80. juniper_data/tests/unit/test_main.py +127 -0
  81. juniper_data/tests/unit/test_middleware.py +79 -0
  82. juniper_data/tests/unit/test_mnist_generator.py +370 -0
  83. juniper_data/tests/unit/test_postgres_store.py +490 -0
  84. juniper_data/tests/unit/test_redis_store.py +500 -0
  85. juniper_data/tests/unit/test_security.py +281 -0
  86. juniper_data/tests/unit/test_security_boundaries.py +517 -0
  87. juniper_data/tests/unit/test_spiral_generator.py +566 -0
  88. juniper_data/tests/unit/test_split.py +245 -0
  89. juniper_data/tests/unit/test_storage.py +767 -0
  90. juniper_data/tests/unit/test_xor_generator.py +223 -0
  91. juniper_data-0.4.2.dist-info/METADATA +216 -0
  92. juniper_data-0.4.2.dist-info/RECORD +95 -0
  93. juniper_data-0.4.2.dist-info/WHEEL +5 -0
  94. juniper_data-0.4.2.dist-info/licenses/LICENSE +9 -0
  95. juniper_data-0.4.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,223 @@
1
+ """Unit tests for the XOR dataset generator."""
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ from juniper_data.generators.xor import VERSION, XorGenerator, XorParams, get_schema
7
+
8
+
9
+ @pytest.mark.unit
10
+ @pytest.mark.generators
11
+ class TestXorParams:
12
+ """Tests for XorParams validation."""
13
+
14
+ def test_default_params(self) -> None:
15
+ """Default parameters are valid."""
16
+ params = XorParams()
17
+ assert params.n_points_per_quadrant == 50
18
+ assert params.x_range == 1.0
19
+ assert params.y_range == 1.0
20
+ assert params.margin == 0.1
21
+ assert params.noise == 0.0
22
+ assert params.train_ratio == 0.8
23
+ assert params.test_ratio == 0.2
24
+
25
+ def test_custom_params(self) -> None:
26
+ """Custom parameters are accepted."""
27
+ params = XorParams(
28
+ n_points_per_quadrant=100,
29
+ x_range=2.0,
30
+ y_range=3.0,
31
+ margin=0.2,
32
+ noise=0.1,
33
+ seed=42,
34
+ train_ratio=0.7,
35
+ test_ratio=0.3,
36
+ )
37
+ assert params.n_points_per_quadrant == 100
38
+ assert params.x_range == 2.0
39
+ assert params.seed == 42
40
+
41
+ def test_invalid_n_points(self) -> None:
42
+ """n_points_per_quadrant must be >= 1."""
43
+ with pytest.raises(ValueError):
44
+ XorParams(n_points_per_quadrant=0)
45
+
46
+ def test_invalid_x_range(self) -> None:
47
+ """x_range must be > 0."""
48
+ with pytest.raises(ValueError):
49
+ XorParams(x_range=0)
50
+
51
+ def test_invalid_train_ratio(self) -> None:
52
+ """train_ratio must be in (0, 1]."""
53
+ with pytest.raises(ValueError):
54
+ XorParams(train_ratio=0)
55
+ with pytest.raises(ValueError):
56
+ XorParams(train_ratio=1.5)
57
+
58
+
59
+ @pytest.mark.unit
60
+ @pytest.mark.generators
61
+ class TestXorGenerator:
62
+ """Tests for XorGenerator functionality."""
63
+
64
+ def test_generate_correct_shapes(self) -> None:
65
+ """Generated arrays have correct shapes."""
66
+ params = XorParams(n_points_per_quadrant=25, seed=42)
67
+ result = XorGenerator.generate(params)
68
+
69
+ n_total = 4 * 25
70
+ n_train = int(n_total * 0.8)
71
+ n_test = n_total - n_train
72
+
73
+ assert result["X_train"].shape == (n_train, 2)
74
+ assert result["y_train"].shape == (n_train, 2)
75
+ assert result["X_test"].shape == (n_test, 2)
76
+ assert result["y_test"].shape == (n_test, 2)
77
+ assert result["X_full"].shape == (n_total, 2)
78
+ assert result["y_full"].shape == (n_total, 2)
79
+
80
+ def test_generate_correct_dtypes(self) -> None:
81
+ """Generated arrays have float32 dtype."""
82
+ params = XorParams(n_points_per_quadrant=10, seed=42)
83
+ result = XorGenerator.generate(params)
84
+
85
+ for key in result:
86
+ assert result[key].dtype == np.float32
87
+
88
+ def test_generate_deterministic_with_seed(self) -> None:
89
+ """Same seed produces identical data."""
90
+ params = XorParams(n_points_per_quadrant=20, seed=42)
91
+
92
+ result1 = XorGenerator.generate(params)
93
+ result2 = XorGenerator.generate(params)
94
+
95
+ np.testing.assert_array_equal(result1["X_full"], result2["X_full"])
96
+ np.testing.assert_array_equal(result1["y_full"], result2["y_full"])
97
+
98
+ def test_generate_different_seeds_different_data(self) -> None:
99
+ """Different seeds produce different data."""
100
+ params1 = XorParams(n_points_per_quadrant=20, seed=42)
101
+ params2 = XorParams(n_points_per_quadrant=20, seed=123)
102
+
103
+ result1 = XorGenerator.generate(params1)
104
+ result2 = XorGenerator.generate(params2)
105
+
106
+ assert not np.array_equal(result1["X_full"], result2["X_full"])
107
+
108
+ def test_generate_one_hot_labels(self) -> None:
109
+ """Labels are valid one-hot encodings."""
110
+ params = XorParams(n_points_per_quadrant=10, seed=42)
111
+ result = XorGenerator.generate(params)
112
+
113
+ y_full = result["y_full"]
114
+ row_sums = y_full.sum(axis=1)
115
+ np.testing.assert_array_almost_equal(row_sums, np.ones(len(y_full)))
116
+
117
+ assert set(np.unique(y_full)) == {0.0, 1.0}
118
+
119
+ def test_generate_class_distribution(self) -> None:
120
+ """Classes are balanced (equal quadrants for each class)."""
121
+ params = XorParams(n_points_per_quadrant=25, seed=42)
122
+ result = XorGenerator.generate(params)
123
+
124
+ y_full = result["y_full"]
125
+ class_0_count = y_full[:, 0].sum()
126
+ class_1_count = y_full[:, 1].sum()
127
+
128
+ assert class_0_count == 50
129
+ assert class_1_count == 50
130
+
131
+ def test_generate_quadrant_distribution(self) -> None:
132
+ """Points are in correct quadrants based on class."""
133
+ params = XorParams(n_points_per_quadrant=50, margin=0.1, seed=42, shuffle=False, noise=0)
134
+ result = XorGenerator.generate(params)
135
+
136
+ X = result["X_full"]
137
+ y = result["y_full"]
138
+ n = 50
139
+
140
+ q1_x = X[0:n, 0]
141
+ q1_y = X[0:n, 1]
142
+ assert np.all(q1_x > 0)
143
+ assert np.all(q1_y > 0)
144
+ assert np.all(y[0:n, 0] == 1)
145
+
146
+ q2_x = X[n : 2 * n, 0]
147
+ q2_y = X[n : 2 * n, 1]
148
+ assert np.all(q2_x < 0)
149
+ assert np.all(q2_y > 0)
150
+ assert np.all(y[n : 2 * n, 1] == 1)
151
+
152
+ q3_x = X[2 * n : 3 * n, 0]
153
+ q3_y = X[2 * n : 3 * n, 1]
154
+ assert np.all(q3_x < 0)
155
+ assert np.all(q3_y < 0)
156
+ assert np.all(y[2 * n : 3 * n, 0] == 1)
157
+
158
+ q4_x = X[3 * n : 4 * n, 0]
159
+ q4_y = X[3 * n : 4 * n, 1]
160
+ assert np.all(q4_x > 0)
161
+ assert np.all(q4_y < 0)
162
+ assert np.all(y[3 * n : 4 * n, 1] == 1)
163
+
164
+ def test_generate_with_noise(self) -> None:
165
+ """Noise is applied when specified."""
166
+ params_no_noise = XorParams(n_points_per_quadrant=50, noise=0, seed=42)
167
+ params_with_noise = XorParams(n_points_per_quadrant=50, noise=0.5, seed=42)
168
+
169
+ result_no_noise = XorGenerator.generate(params_no_noise)
170
+ result_with_noise = XorGenerator.generate(params_with_noise)
171
+
172
+ assert not np.array_equal(result_no_noise["X_full"], result_with_noise["X_full"])
173
+
174
+ def test_generate_respects_range(self) -> None:
175
+ """Points are within specified range (before noise)."""
176
+ params = XorParams(n_points_per_quadrant=100, x_range=2.0, y_range=3.0, margin=0.2, noise=0, seed=42)
177
+ result = XorGenerator.generate(params)
178
+
179
+ X = result["X_full"]
180
+ assert np.all(np.abs(X[:, 0]) <= 2.0)
181
+ assert np.all(np.abs(X[:, 1]) <= 3.0)
182
+
183
+ def test_generate_respects_margin(self) -> None:
184
+ """Points respect margin around axes."""
185
+ params = XorParams(n_points_per_quadrant=100, margin=0.2, noise=0, seed=42)
186
+ result = XorGenerator.generate(params)
187
+
188
+ X = result["X_full"]
189
+ assert np.all(np.abs(X[:, 0]) >= 0.2)
190
+ assert np.all(np.abs(X[:, 1]) >= 0.2)
191
+
192
+
193
+ @pytest.mark.unit
194
+ @pytest.mark.generators
195
+ class TestXorGetSchema:
196
+ """Tests for get_schema function."""
197
+
198
+ def test_get_schema_returns_dict(self) -> None:
199
+ """get_schema returns a dictionary."""
200
+ schema = get_schema()
201
+ assert isinstance(schema, dict)
202
+
203
+ def test_get_schema_has_properties(self) -> None:
204
+ """Schema has properties field."""
205
+ schema = get_schema()
206
+ assert "properties" in schema
207
+ assert "n_points_per_quadrant" in schema["properties"]
208
+ assert "x_range" in schema["properties"]
209
+ assert "margin" in schema["properties"]
210
+ assert "noise" in schema["properties"]
211
+
212
+
213
+ @pytest.mark.unit
214
+ @pytest.mark.generators
215
+ class TestXorVersion:
216
+ """Tests for version constant."""
217
+
218
+ def test_version_format(self) -> None:
219
+ """Version follows semver format."""
220
+ parts = VERSION.split(".")
221
+ assert len(parts) == 3
222
+ for part in parts:
223
+ assert part.isdigit()
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: juniper-data
3
+ Version: 0.4.2
4
+ Summary: Dataset generation and management service for the Juniper ecosystem
5
+ Author: Paul Calnon
6
+ License: MIT
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: numpy>=1.24.0
11
+ Requires-Dist: pydantic>=2.0.0
12
+ Requires-Dist: python-dotenv>=1.0.0
13
+ Provides-Extra: arc-agi
14
+ Requires-Dist: arc-agi>=0.9.0; extra == "arc-agi"
15
+ Provides-Extra: api
16
+ Requires-Dist: fastapi>=0.100.0; extra == "api"
17
+ Requires-Dist: uvicorn[standard]>=0.23.0; extra == "api"
18
+ Requires-Dist: pydantic-settings>=2.0.0; extra == "api"
19
+ Provides-Extra: test
20
+ Requires-Dist: pytest>=7.0.0; extra == "test"
21
+ Requires-Dist: pytest-cov>=4.0.0; extra == "test"
22
+ Requires-Dist: pytest-timeout>=2.2.0; extra == "test"
23
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
24
+ Requires-Dist: pytest-benchmark>=4.0.0; extra == "test"
25
+ Requires-Dist: httpx>=0.24.0; extra == "test"
26
+ Requires-Dist: coverage[toml]>=7.0.0; extra == "test"
27
+ Requires-Dist: juniper-data-client>=0.3.0; extra == "test"
28
+ Provides-Extra: dev
29
+ Requires-Dist: ruff>=0.9.0; extra == "dev"
30
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
31
+ Requires-Dist: bandit[sarif]>=1.7.9; extra == "dev"
32
+ Requires-Dist: pip-audit>=2.7.0; extra == "dev"
33
+ Requires-Dist: pre-commit>=3.0.0; extra == "dev"
34
+ Provides-Extra: all
35
+ Requires-Dist: juniper-data[api,arc-agi,dev,test]; extra == "all"
36
+ Dynamic: license-file
37
+
38
+ # Juniper Data
39
+
40
+ Dataset generation and management service for the Juniper ecosystem.
41
+
42
+ ## Overview
43
+
44
+ Juniper Data provides a centralized service for generating, storing, and serving datasets used by the Juniper neural network projects. It supports various dataset types including the classic two-spiral classification problem.
45
+
46
+ ## Ecosystem Compatibility
47
+
48
+ This service is part of the [Juniper](https://github.com/pcalnon/juniper-ml) ecosystem.
49
+ Verified compatible versions:
50
+
51
+ | juniper-data | juniper-cascor | juniper-canopy | data-client | cascor-client | cascor-worker |
52
+ |---|---|---|---|---|---|
53
+ | 0.4.x | 0.3.x | 0.2.x | >=0.3.1 | >=0.1.0 | >=0.1.0 |
54
+
55
+ For full-stack Docker deployment and integration tests, see [juniper-deploy](https://github.com/pcalnon/juniper-deploy).
56
+
57
+ ## Architecture
58
+
59
+ JuniperData is the **foundational data layer** of the Juniper ecosystem. JuniperCascor and juniper-canopy both call JuniperData to generate and retrieve datasets.
60
+
61
+ ```
62
+ ┌─────────────────────┐ REST+WS ┌──────────────────────┐
63
+ │ juniper-canopy │ ◄──────────────► │ JuniperCascor │
64
+ │ Dashboard │ │ Training Svc │
65
+ │ Port 8050 │ │ Port 8200 │
66
+ └──────────┬──────────┘ └──────────┬───────────┘
67
+ │ REST │ REST
68
+ ▼ ▼
69
+ ┌──────────────────────────────────────────────────────────────┐
70
+ │ JuniperData ◄── (this service) │
71
+ │ Dataset Service · Port 8100 │
72
+ └──────────────────────────────────────────────────────────────┘
73
+ ```
74
+
75
+ **Data contract**: datasets are served as NPZ archives with keys `X_train`, `y_train`, `X_test`, `y_test`, `X_full`, `y_full` (all `float32`).
76
+
77
+ ## Related Services
78
+
79
+ | Service | Relationship | Environment Variable |
80
+ |---------|-------------|---------------------|
81
+ | [juniper-cascor](https://github.com/pcalnon/juniper-cascor) | Consumes JuniperData for training datasets | `JUNIPER_DATA_URL=http://localhost:8100` |
82
+ | [juniper-canopy](https://github.com/pcalnon/juniper-canopy) | Consumes JuniperData for visualization data | `JUNIPER_DATA_URL=http://localhost:8100` |
83
+ | [juniper-data-client](https://github.com/pcalnon/juniper-data-client) | PyPI client library for this service | `pip install juniper-data-client` |
84
+
85
+ ### Service Configuration
86
+
87
+ | Variable | Default | Description |
88
+ |----------|---------|-------------|
89
+ | `JUNIPER_DATA_HOST` | `0.0.0.0` | Listen address |
90
+ | `JUNIPER_DATA_PORT` | `8100` | Service port |
91
+ | `JUNIPER_DATA_LOG_LEVEL` | `INFO` | Log verbosity |
92
+
93
+ ### Docker Deployment
94
+
95
+ ```bash
96
+ # Full stack with all three services:
97
+ git clone https://github.com/pcalnon/juniper-deploy.git
98
+ cd juniper-deploy && docker compose up --build
99
+ ```
100
+
101
+ ## Installation
102
+
103
+ ### Basic Installation
104
+
105
+ ```bash
106
+ pip install -e .
107
+ ```
108
+
109
+ ### With API Support
110
+
111
+ ```bash
112
+ pip install -e ".[api]"
113
+ ```
114
+
115
+ ### Development Installation
116
+
117
+ ```bash
118
+ pip install -e ".[dev]"
119
+ ```
120
+
121
+ ### Full Installation
122
+
123
+ ```bash
124
+ pip install -e ".[all]"
125
+ ```
126
+
127
+ ## Quick Start
128
+
129
+ ### Generate a Spiral Dataset
130
+
131
+ ```python
132
+ from juniper_data.generators.spiral import SpiralGenerator
133
+
134
+ generator = SpiralGenerator()
135
+ dataset = generator.generate(n_points=100, n_spirals=2, noise=0.1)
136
+ ```
137
+
138
+ ### Start the API Server
139
+
140
+ ```bash
141
+ uvicorn juniper_data.api.app:app --reload
142
+ ```
143
+
144
+ ## API Endpoints
145
+
146
+ | Endpoint | Method | Description |
147
+ | ------------------------------- | ------ | ---------------------------------- |
148
+ | `/v1/health` | GET | Health check endpoint |
149
+ | `/v1/datasets` | GET | List available datasets |
150
+ | `/v1/datasets/{id}` | GET | Get a specific dataset |
151
+ | `/v1/generators/spiral` | POST | Generate a new spiral dataset |
152
+ | `/v1/generators/spiral/config` | GET | Get spiral generator configuration |
153
+
154
+ ## Project Structure
155
+
156
+ ```bash
157
+ JuniperData/
158
+ ├── juniper_data/
159
+ │ ├── core/ # Core functionality and base classes
160
+ │ ├── generators/ # Dataset generators
161
+ │ │ └── spiral/ # Spiral dataset generator
162
+ │ ├── storage/ # Dataset persistence layer
163
+ │ └── api/ # FastAPI application
164
+ │ └── routes/ # API route handlers
165
+ ├── tests/
166
+ │ ├── unit/ # Unit tests
167
+ │ └── integration/ # Integration tests
168
+ ├── pyproject.toml # Project configuration
169
+ └── README.md # This file
170
+ ```
171
+
172
+ ## Development
173
+
174
+ ### Running Tests
175
+
176
+ ```bash
177
+ pytest
178
+ ```
179
+
180
+ ### Running Tests with Coverage
181
+
182
+ ```bash
183
+ pytest --cov=juniper_data --cov-report=html
184
+ ```
185
+
186
+ ### Code Formatting
187
+
188
+ ```bash
189
+ black juniper_data tests
190
+ isort juniper_data tests
191
+ ```
192
+
193
+ ### Type Checking
194
+
195
+ ```bash
196
+ mypy juniper_data
197
+ ```
198
+
199
+ ## Juniper Ecosystem
200
+
201
+ | Repository | Description |
202
+ |-----------|-------------|
203
+ | [juniper-data](https://github.com/pcalnon/juniper-data) | Dataset generation service (this repo) |
204
+ | [juniper-cascor](https://github.com/pcalnon/juniper-cascor) | CasCor neural network training service |
205
+ | [juniper-canopy](https://github.com/pcalnon/juniper-canopy) | Real-time monitoring dashboard |
206
+ | [juniper-data-client](https://github.com/pcalnon/juniper-data-client) | PyPI: `juniper-data-client` |
207
+ | [juniper-cascor-client](https://github.com/pcalnon/juniper-cascor-client) | PyPI: `juniper-cascor-client` |
208
+ | [juniper-cascor-worker](https://github.com/pcalnon/juniper-cascor-worker) | PyPI: `juniper-cascor-worker` |
209
+
210
+ ## License
211
+
212
+ MIT License - Copyright (c) 2024-2026 Paul Calnon
213
+
214
+ ## Git Leaks
215
+
216
+ ![gitleaks badge](https://img.shields.io/badge/protected%20by-gitleaks-blue)
@@ -0,0 +1,95 @@
1
+ juniper_data/__init__.py,sha256=f-YIxV_v8g_ZCO3-NouWqAvBXUBQRlqZGV0iSH-a0MQ,2744
2
+ juniper_data/__main__.py,sha256=aZ5Z2vdYmBVMgS_PO2iVGbDr5kHDrTZDt0kc1Yw0XY0,2005
3
+ juniper_data/api/__init__.py,sha256=ivCMO5TtsakyWGfJG0Uvvwh1S4atQbYb23FZPevYZSc,186
4
+ juniper_data/api/app.py,sha256=Vc_DLVUq4Qvab6x0S6N1X2orxXZC4RxYCAOHyQ8nCr0,3642
5
+ juniper_data/api/middleware.py,sha256=jnZ2L7qWOTlxTFps9-QtOonX_7jhKGhKkt1mriRWMwI,2830
6
+ juniper_data/api/security.py,sha256=Hd3pmGNlmbnqvRcbTm78Ow65XtUZK2RuXZunBL1ebCc,7269
7
+ juniper_data/api/settings.py,sha256=Ek90KdHDa7zv9imNCLrm1U6YaSQ1b9eNxZCk0wB__jk,4839
8
+ juniper_data/api/routes/__init__.py,sha256=Zun__tMjPacvwVLfEyFbCMm2BqsOXMvMScifKqpx_xc,132
9
+ juniper_data/api/routes/datasets.py,sha256=pRY0fAM8LZ20ITz49Waon4sjZuSJkB9RaM1JddKNvcI,12587
10
+ juniper_data/api/routes/generators.py,sha256=Ix6m7sgPRsHuBVrZfa3IDxU2IhQi1_HJ5TlH9BwT6JQ,5115
11
+ juniper_data/api/routes/health.py,sha256=9Z8QyKcO3SnNzR1_0oMyVXH09-uZBJjLCQWgNqA7r3E,1440
12
+ juniper_data/core/__init__.py,sha256=3zvR-Dmj3jJNoCwnZ5F9els42U7eIS5y_E43vrMy-DY,787
13
+ juniper_data/core/artifacts.py,sha256=ldxICuQA0wVG-_NMStfk5pLZ16TTsV_0AyKowkZ1T1o,1830
14
+ juniper_data/core/dataset_id.py,sha256=5bR8Nm0S8NpKixRLYTnYYeGU2sn3RO1mQZ4DdRJW0eg,1197
15
+ juniper_data/core/models.py,sha256=wwIw77Tb6BFV1i10zf5MvqJMy9bmovh-D41WxyF0WLw,3392
16
+ juniper_data/core/split.py,sha256=cL7_WItaLqFshyuc48GX49jYxUmTKTuNuoF2I_4R0D4,3828
17
+ juniper_data/generators/__init__.py,sha256=lyPQAXGolK4K5xUlefV5blznHtiuqBamUIQ6DZYX_xw,419
18
+ juniper_data/generators/arc_agi/__init__.py,sha256=cgrwth7zfJPUlIrr0sGmvWb9VCXrHE8SKxKXOYzQyiU,315
19
+ juniper_data/generators/arc_agi/generator.py,sha256=6mdq_E_uYZ0lPhUyWxRRG1ptyPKa2cb2Ajh-TW3usOs,8013
20
+ juniper_data/generators/arc_agi/params.py,sha256=Xk2CoZB1fLF74IvzKoCF-V4Cf1x_d-fm1ipWMdJKBc8,1996
21
+ juniper_data/generators/checkerboard/__init__.py,sha256=4o8qcmkylkX0sUTUsSvBaEn8KcObxEQamutFQPUVlo4,351
22
+ juniper_data/generators/checkerboard/generator.py,sha256=-gHa4PI8S_xUsGM5D0TsX5sBqpbKNw_T-G2ScQobvAg,3610
23
+ juniper_data/generators/checkerboard/params.py,sha256=9hp_wQLTd7Qpz1tX-bhIVO1gslNFnbAzgOs2HLrkVBU,1292
24
+ juniper_data/generators/circles/__init__.py,sha256=bqsMH10l0P8_0OwczX9Yr7W5VBSk-KmVtYvhLu0Z1us,310
25
+ juniper_data/generators/circles/generator.py,sha256=xjH9IQlo9xAanznnA16X_g9F1yEzjItZyREWVWHycE0,3664
26
+ juniper_data/generators/circles/params.py,sha256=N9HzOuqBTrNsic9KMWFXRJBeqI8w66xMD08lh08mvxY,1342
27
+ juniper_data/generators/csv_import/__init__.py,sha256=0G8cSCWNJT16spZFXJ1GQ_4bMqtUbStS6rlc6knmIJg,335
28
+ juniper_data/generators/csv_import/generator.py,sha256=co-wbahAkYOyF4QauqtEezdALoHrAywSDI0b8Ri4m9o,6966
29
+ juniper_data/generators/csv_import/params.py,sha256=xODc4H1k9qMt-RsbTCpwG11EVcyRrW0UVcTkcVfGFsk,1627
30
+ juniper_data/generators/gaussian/__init__.py,sha256=CcAon3pYzU7hwqYPFa8y6kDY9qqrAcTDVRQtuymwF4w,312
31
+ juniper_data/generators/gaussian/generator.py,sha256=OS-7qQDBLdAKcfNYwvGCiL5nxiXr5nKQ1AiaM1ib8uQ,5362
32
+ juniper_data/generators/gaussian/params.py,sha256=RcDuYVcIbtGn7GAWxkoVypSIINeyNAEO-W9-C03TjDE,2356
33
+ juniper_data/generators/mnist/__init__.py,sha256=Ax5fi21Eh0ykN_vMu9Lzj_aLDi6fb4y5M3G5dRuBqYM,288
34
+ juniper_data/generators/mnist/generator.py,sha256=exNfvoS5iMIKOi3axWJbbsG3Rbb35dmvwQq0fmJDK9U,3807
35
+ juniper_data/generators/mnist/params.py,sha256=cheR4V5Gvp9ABXhDlfxYEb01Wr466CSHcvcbW5DmSbA,1351
36
+ juniper_data/generators/spiral/__init__.py,sha256=RK02ztKeqWon-ILhyH4SjeAtz9PCZDcrsBpO4wVoc50,1365
37
+ juniper_data/generators/spiral/defaults.py,sha256=OPeixDRXh2X7NKUPUyzlml0qYtj7DrqDG3t18NbFZyo,1077
38
+ juniper_data/generators/spiral/generator.py,sha256=KYDV6cd9YoFCOaJURRJd_yJplG-TghswK8OTLaBe0cw,7100
39
+ juniper_data/generators/spiral/params.py,sha256=cch0nca0of-rvxzdSn91khGmNbPa7bGgfosW03IJ13E,4906
40
+ juniper_data/generators/xor/__init__.py,sha256=Sf_QCNFGpVmaAIFDDFuSYEje7hmsR9lWbfWSxrp7fwI,271
41
+ juniper_data/generators/xor/generator.py,sha256=HGfddoDPzwFUxHsmSJEPht42y-9RbNtQeY178tbrnbg,4832
42
+ juniper_data/generators/xor/params.py,sha256=6Pta8M1NlF_6J4hLNl2WmnmV7eakjnjOFHPVC9d2xQQ,1379
43
+ juniper_data/storage/__init__.py,sha256=tCaD9PfCAVWRRgH975S_VSG9hvE0t0xcXhKDRoiGEz4,3658
44
+ juniper_data/storage/base.py,sha256=cbkPtOSBZqn1gq3RSz0Amg9A6NJaADIITp8W5Hjmr7Y,8608
45
+ juniper_data/storage/cached.py,sha256=bo94ltUI8HDx4pEXq0uQUsBXWcSsxko-syyDrVgybS8,6674
46
+ juniper_data/storage/hf_store.py,sha256=D_7OYBakcVBgBYVC7d8-JC3BoxIHxanxyiS1xY42neg,8515
47
+ juniper_data/storage/kaggle_store.py,sha256=rIQ-1k2Dr5QcpO64eed6NzKVTVWVHUXbidH0bszztQ8,10799
48
+ juniper_data/storage/local_fs.py,sha256=s2biQkjoWuKARz7P3pUa6-S6gBKFdRCikJuRNbqZVwA,7366
49
+ juniper_data/storage/memory.py,sha256=_UKrqG20kXGscHQw_IhWpBBa5Q4l589tfeCYQXCgXa8,4059
50
+ juniper_data/storage/postgres_store.py,sha256=hyHKzc16JtiFr__lRAyLFNnZ4GWbNc1O5BBXtTZONmo,13416
51
+ juniper_data/storage/redis_store.py,sha256=gjs05DHxT3sNyhD1ZjBy--xuwVrd2bP17Mq97iPl-W0,8011
52
+ juniper_data/tests/__init__.py,sha256=w63Rss-gcq9r_60LPWJkbZTUUOLfQlgqjZYTX-jT0Xg,35
53
+ juniper_data/tests/conftest.py,sha256=Y44G_fBs7hdypuXVE1TVVf_VRReAW9BBiG8_p8x8MYY,1909
54
+ juniper_data/tests/fixtures/generate_golden_datasets.py,sha256=pL54BRaG5xnqu5GbC7A5r5e2uzSE5yIas7YYPzJLIQw,6497
55
+ juniper_data/tests/integration/__init__.py,sha256=s-CLb60cwfh53nHtCf7mjmtAJ_Z3duzYT7g-UhjQS5Y,42
56
+ juniper_data/tests/integration/test_api.py,sha256=UbXgGmAps7mg43e8FqOBLfhJ7AP93jU4a2PpKB8bft4,10086
57
+ juniper_data/tests/integration/test_e2e_workflow.py,sha256=8ad9qig5q0Aka5Y8otJGXxA8Q2zGUclzDM_GxisBlUg,15360
58
+ juniper_data/tests/integration/test_lifecycle_api.py,sha256=kfJ6clcrMdhQEzAi1TH5wEEBTG9hz5IFEYI4V8I7UmI,11606
59
+ juniper_data/tests/integration/test_security_integration.py,sha256=2JNiTRENjkxCyiprsO5Q6tsgkGlbVK6CrGdxzkP0wLg,7186
60
+ juniper_data/tests/integration/test_storage_workflow.py,sha256=Oc0XvMdGRBxG2KiM6-K2jOvUeF92evpvbikwqY3StUc,10156
61
+ juniper_data/tests/performance/__init__.py,sha256=PqIqrY081KlNAPL4l014W5cYlEpD-iTp0JGRr4GuD1w,52
62
+ juniper_data/tests/performance/test_generator_benchmarks.py,sha256=t7z60VUJjuO-Srdpxh6n3VX4RW8CduDSOcb7tHmXInk,8718
63
+ juniper_data/tests/performance/test_storage_benchmarks.py,sha256=JqzCYOiiiwR5jB5P4nVpSnwEKsMrDrKrsHunN8sey0w,11140
64
+ juniper_data/tests/unit/__init__.py,sha256=zNL9fUJO-udWbVm128WjFl33SGlFV8Z9--9w5wa45F0,35
65
+ juniper_data/tests/unit/test_api_app.py,sha256=IgSRws5U9hE4ATcuvewT4WcbKX5M85G_NsSryuonpac,8139
66
+ juniper_data/tests/unit/test_api_routes.py,sha256=q1rSREG5duNfNRYNpfH_2j18187PtBcvUL4Nnuh_kks,15608
67
+ juniper_data/tests/unit/test_api_settings.py,sha256=zRITgvV3R2loPQDcyLxm3hkEsj7T28rGX1eB3X0ZD7w,3197
68
+ juniper_data/tests/unit/test_arc_agi_generator.py,sha256=9YwAG9EoU57oQFTCGY9cor2QihUTpOscGfSonMfpQXY,19238
69
+ juniper_data/tests/unit/test_artifacts.py,sha256=lmxY042dJ2yr5QIILtC5QpcZa4mb37FO46qEz3GtUtU,4928
70
+ juniper_data/tests/unit/test_cached_store.py,sha256=3YL4SWN_VEme7QfQYMJ39D4QNdCm5UMiI6Kn0pbwY2U,14830
71
+ juniper_data/tests/unit/test_checkerboard_generator.py,sha256=qbM0EHHRcTDQL9aMrme33Pqz8G4k6g1riVx0VcV8ExU,8056
72
+ juniper_data/tests/unit/test_circles_generator.py,sha256=O06rbL_k_gEUqBGAuzlphci4AWdpQnzkrbtB402crbQ,8971
73
+ juniper_data/tests/unit/test_csv_import_generator.py,sha256=Zt2MUkbNT5zR2EoMGZevlYjzYSEuQR4F-e99cCBfPcw,12279
74
+ juniper_data/tests/unit/test_dataset_id.py,sha256=rdFiX4VOx9Dc-s8dW9qTV17XS2RBmz3mCmhUH02IEFA,5917
75
+ juniper_data/tests/unit/test_gaussian_generator.py,sha256=etTAFt-0l_PvbY3xNCXewK9cvwmL_boz9X0Z-vSOaHI,11849
76
+ juniper_data/tests/unit/test_hf_store.py,sha256=pKEJOj5S_DW-ZWxrIjGO5g0cvUsaCnSU0Ex3e1oWPic,16481
77
+ juniper_data/tests/unit/test_init.py,sha256=AC0hS76V8pQxIbANcnisYOhoWxS28YW4X0E7OPQ1t94,4099
78
+ juniper_data/tests/unit/test_kaggle_store.py,sha256=YDthyg1oUR42usi7_I7uTDnMXmhk2nfVf55gAb6dz_8,20524
79
+ juniper_data/tests/unit/test_lifecycle.py,sha256=EIQzO0sk3as8uQL_D1PHU0n13qQv-183ZLJDn2JBzWI,15504
80
+ juniper_data/tests/unit/test_main.py,sha256=e_NC71xbgdu9xGRameLNzYrrQV4l1PuBsfxDszsw7Jo,5565
81
+ juniper_data/tests/unit/test_middleware.py,sha256=8qhPzzEhnmEeS9gpgzboPSjpR3Jb_310Lop0HA2C1tg,2863
82
+ juniper_data/tests/unit/test_mnist_generator.py,sha256=mNRnt7sYJStNHJXuauyAKtKQ0Hf3VDqgAtrqKU3eMRI,13294
83
+ juniper_data/tests/unit/test_postgres_store.py,sha256=vxOiSqfAfgUEBdvKJpjx_qVDQ6hXe7NjhoxKawm8EFM,18675
84
+ juniper_data/tests/unit/test_redis_store.py,sha256=6oailneNwaUTTRhl5-kLgN5WDlxCjDknWnrk6Dhw3kU,17807
85
+ juniper_data/tests/unit/test_security.py,sha256=tHlLXUFQHqkf1lQcoQILYjMBMqy4A97UtTaktTlACFE,9797
86
+ juniper_data/tests/unit/test_security_boundaries.py,sha256=_QiPPIQR7f9a-gie3xwk57CdLrQ1HqRZUQ7bG5QzQqI,23355
87
+ juniper_data/tests/unit/test_spiral_generator.py,sha256=zKcRsV5h5hKavUA7yNFeTJpk8_0eXYJg8nr4OB4icyw,21145
88
+ juniper_data/tests/unit/test_split.py,sha256=6kYLZHRjV59_LKPJoyzdW37Gxtz2cfexCO7745q5JTc,9409
89
+ juniper_data/tests/unit/test_storage.py,sha256=gVV6uFGwV_nUh7LmQ8b4B0eH8RbX-I7w-ZK7Oz_SQBM,29626
90
+ juniper_data/tests/unit/test_xor_generator.py,sha256=GY0N6Iq0SCXrWPBob3Ob-Cf9oOdHhR26C80Uz_o1ysA,7689
91
+ juniper_data-0.4.2.dist-info/licenses/LICENSE,sha256=gS6kn2rddVUTz-UTtrOqHcqE5w4qYpt7gmKcLG_RxZ4,1091
92
+ juniper_data-0.4.2.dist-info/METADATA,sha256=PKr6RSoWSigVe9N62q7-YlMIW2NSr47MN_H55CaCcgI,7679
93
+ juniper_data-0.4.2.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
94
+ juniper_data-0.4.2.dist-info/top_level.txt,sha256=Mdnkl3i3xziR8cu3cMfNrKBAIACp1RB6e1Ks5MWHXa0,13
95
+ juniper_data-0.4.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,9 @@
1
+ # Juniper Canopy project
2
+
3
+ Copyright 2024, 2025 Paul Calnon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
1
+ juniper_data