diff --git a/notebooks/scenarios/bigquery/00-start-and-configure-server-and-admins.ipynb b/notebooks/scenarios/bigquery/00-start-and-configure-server-and-admins.ipynb index 213c4c6d405..8235576b5f5 100644 --- a/notebooks/scenarios/bigquery/00-start-and-configure-server-and-admins.ipynb +++ b/notebooks/scenarios/bigquery/00-start-and-configure-server-and-admins.ipynb @@ -212,6 +212,13 @@ "source": [ "server.land()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -230,7 +237,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.10.13" } }, "nbformat": 4, diff --git a/notebooks/scenarios/bigquery/01-setup-datasite.ipynb b/notebooks/scenarios/bigquery/01-setup-datasite.ipynb index 51e4efb58c7..c734b07298e 100644 --- a/notebooks/scenarios/bigquery/01-setup-datasite.ipynb +++ b/notebooks/scenarios/bigquery/01-setup-datasite.ipynb @@ -402,7 +402,9 @@ "source": [ "worker_pool_name = \"bigquery-pool\"\n", "custom_pool_pod_annotations = {\"bigquery-custom-pool\": \"Pod annotation for bigquery\"}\n", - "custom_pool_pod_labels = {\"bigquery-custom-pool\": \"Pod_label_for_bigquery\"}" + "custom_pool_pod_labels = {\"bigquery-custom-pool\": \"Pod_label_for_bigquery\"}\n", + "\n", + "num_workers = int(os.environ.get(\"NUM_TEST_WORKERS\", 1))" ] }, { @@ -428,7 +430,9 @@ "outputs": [], "source": [ "if environment == \"remote\":\n", - " result = high_client.worker_pools.scale(number=2, pool_name=worker_pool_name)\n", + " result = high_client.worker_pools.scale(\n", + " number=num_workers, pool_name=worker_pool_name\n", + " )\n", " print(result)" ] }, @@ -476,6 +480,13 @@ "source": [ "server.land()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -494,7 +505,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.10.13" } }, "nbformat": 4, diff --git a/notebooks/scenarios/bigquery/011-users-emails-passwords.ipynb b/notebooks/scenarios/bigquery/011-users-emails-passwords.ipynb index 45e6e10d847..c585aa55a07 100644 --- a/notebooks/scenarios/bigquery/011-users-emails-passwords.ipynb +++ b/notebooks/scenarios/bigquery/011-users-emails-passwords.ipynb @@ -129,14 +129,32 @@ "# high_client.api.services.settings.disable_notifications()" ] }, + { + "cell_type": "markdown", + "id": "9", + "metadata": {}, + "source": [ + "# Register users" + ] + }, { "cell_type": "code", "execution_count": null, - "id": "9", + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "num_users = int(os.environ.get(\"NUM_TEST_USERS\", 5))\n", + "print(f\"registering {num_users} users\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11", "metadata": {}, "outputs": [], "source": [ - "num_users = 5\n", "users = []\n", "email_disable_index = 0\n", "reset_password_index = 1\n", @@ -155,7 +173,7 @@ { "cell_type": "code", "execution_count": null, - "id": "10", + "id": "12", "metadata": {}, "outputs": [], "source": [ @@ -165,7 +183,7 @@ { "cell_type": "code", "execution_count": null, - "id": "11", + "id": "13", "metadata": {}, "outputs": [], "source": [ @@ -178,7 +196,7 @@ { "cell_type": "code", "execution_count": null, - "id": "12", + "id": "14", "metadata": {}, "outputs": [], "source": [ @@ -197,7 +215,7 @@ { "cell_type": "code", "execution_count": null, - "id": "13", + "id": "15", "metadata": {}, "outputs": [], "source": [ @@ -222,7 +240,7 @@ { "cell_type": "code", "execution_count": null, - "id": "14", + "id": "16", "metadata": {}, "outputs": [], "source": [ @@ -232,7 +250,7 @@ { "cell_type": "code", "execution_count": null, - "id": "15", + "id": "17", "metadata": {}, "outputs": [], "source": [ @@ -243,7 +261,7 @@ { "cell_type": "code", "execution_count": null, - "id": "16", + "id": "18", "metadata": {}, "outputs": [], "source": [ @@ -257,7 +275,7 @@ { "cell_type": "code", "execution_count": null, - "id": "17", + "id": "19", "metadata": {}, "outputs": [], "source": [ @@ -269,7 +287,7 @@ { "cell_type": "code", "execution_count": null, - "id": "18", + "id": "20", "metadata": {}, "outputs": [], "source": [ @@ -279,7 +297,7 @@ { "cell_type": "code", "execution_count": null, - "id": "19", + "id": "21", "metadata": {}, "outputs": [], "source": [ @@ -290,7 +308,7 @@ { "cell_type": "code", "execution_count": null, - "id": "20", + "id": "22", "metadata": {}, "outputs": [], "source": [ @@ -301,7 +319,7 @@ { "cell_type": "code", "execution_count": null, - "id": "21", + "id": "23", "metadata": {}, "outputs": [], "source": [ @@ -312,7 +330,7 @@ { "cell_type": "code", "execution_count": null, - "id": "22", + "id": "24", "metadata": {}, "outputs": [], "source": [ @@ -323,7 +341,7 @@ { "cell_type": "code", "execution_count": null, - "id": "23", + "id": "25", "metadata": {}, "outputs": [], "source": [ @@ -336,7 +354,7 @@ { "cell_type": "code", "execution_count": null, - "id": "24", + "id": "26", "metadata": {}, "outputs": [], "source": [ @@ -346,7 +364,7 @@ { "cell_type": "code", "execution_count": null, - "id": "25", + "id": "27", "metadata": {}, "outputs": [], "source": [ @@ -357,7 +375,7 @@ { "cell_type": "code", "execution_count": null, - "id": "26", + "id": "28", "metadata": {}, "outputs": [], "source": [ @@ -367,7 +385,7 @@ { "cell_type": "code", "execution_count": null, - "id": "27", + "id": "29", "metadata": {}, "outputs": [], "source": [ @@ -377,12 +395,20 @@ { "cell_type": "code", "execution_count": null, - "id": "28", + "id": "30", "metadata": {}, "outputs": [], "source": [ "server.land()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -401,7 +427,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.10.13" } }, "nbformat": 4, diff --git a/notebooks/scenarios/bigquery/02-configure-api.ipynb b/notebooks/scenarios/bigquery/02-configure-api.ipynb index a1e805bc37e..bcec4a3905e 100644 --- a/notebooks/scenarios/bigquery/02-configure-api.ipynb +++ b/notebooks/scenarios/bigquery/02-configure-api.ipynb @@ -535,7 +535,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.10.13" } }, "nbformat": 4, diff --git a/notebooks/scenarios/bigquery/021-create-jobs.ipynb b/notebooks/scenarios/bigquery/021-create-jobs.ipynb index 9d718e8c24e..c889100e86b 100644 --- a/notebooks/scenarios/bigquery/021-create-jobs.ipynb +++ b/notebooks/scenarios/bigquery/021-create-jobs.ipynb @@ -169,10 +169,9 @@ "metadata": {}, "outputs": [], "source": [ - "# maybe we should assign one of each first, and then randomly generate the rest\n", - "n_per_user = 2\n", + "num_jobs = int(os.environ.get(\"NUM_TEST_JOBS\", 10))\n", "\n", - "jobs = create_jobs(users, n_per_user=n_per_user)" + "jobs = create_jobs(users, total_jobs=num_jobs)" ] }, { @@ -182,7 +181,12 @@ "metadata": {}, "outputs": [], "source": [ - "jobs" + "# stdlib\n", + "from collections import Counter\n", + "\n", + "counts = Counter([j.job_type for j in jobs])\n", + "for k, v in counts.most_common():\n", + " print(f\"number of {k}: {v}\")" ] }, { @@ -220,7 +224,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert len(jobs) == len(users) * n_per_user\n", + "assert len(jobs) == num_jobs\n", "assert all(isinstance(j, TestJob) for j in jobs)\n", "assert all(job.client is not None for job in jobs)" ] @@ -428,7 +432,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.10.13" } }, "nbformat": 4, diff --git a/notebooks/scenarios/bigquery/04-do-review-requests.ipynb b/notebooks/scenarios/bigquery/04-do-review-requests.ipynb index 9af349607d1..011c4bf3e25 100644 --- a/notebooks/scenarios/bigquery/04-do-review-requests.ipynb +++ b/notebooks/scenarios/bigquery/04-do-review-requests.ipynb @@ -253,7 +253,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.10.13" } }, "nbformat": 4, diff --git a/notebooks/scenarios/bigquery/job_helpers.py b/notebooks/scenarios/bigquery/job_helpers.py index b68445152f7..17476ba1867 100644 --- a/notebooks/scenarios/bigquery/job_helpers.py +++ b/notebooks/scenarios/bigquery/job_helpers.py @@ -248,15 +248,14 @@ def create_job_many_columns(user: TestUser) -> TestJob: return job -def create_job(user: TestUser) -> TestJob: +def create_random_job(user: TestUser) -> TestJob: job_func = random.choice(create_job_functions) return job_func(user) -def create_jobs(users: list[TestUser], n_per_user: int = 10) -> list[TestJob]: +def create_jobs(users: list[TestUser], total_jobs: int = 10) -> list[TestJob]: jobs = [] num_users = len(users) - total_jobs = n_per_user * num_users user_index = 0 each_count = 0 # keep making jobs until we have enough @@ -267,7 +266,7 @@ def create_jobs(users: list[TestUser], n_per_user: int = 10) -> list[TestJob]: each_count += 1 else: # otherwise lets get a random one - job_func = create_job + job_func = create_random_job # use the current index of user jobs.append(job_func(users[user_index])) diff --git a/packages/syft/src/syft/protocol/protocol_version.json b/packages/syft/src/syft/protocol/protocol_version.json index d12435881c9..bc025daa762 100644 --- a/packages/syft/src/syft/protocol/protocol_version.json +++ b/packages/syft/src/syft/protocol/protocol_version.json @@ -339,7 +339,7 @@ }, "4": { "version": 4, - "hash": "cf6c1cb55d569af9823d8541ca038806bd350450a919345244ed4f432a099f34", + "hash": "b8067777967a0e06733433e179e549caaf501419d62f7e8474ee33b839e3890d", "action": "add" } }, diff --git a/packages/syft/src/syft/service/settings/settings.py b/packages/syft/src/syft/service/settings/settings.py index 1408ceb0d50..52177507ab3 100644 --- a/packages/syft/src/syft/service/settings/settings.py +++ b/packages/syft/src/syft/service/settings/settings.py @@ -4,6 +4,7 @@ from typing import Any # third party +from pydantic import EmailStr from pydantic import field_validator from pydantic import model_validator from typing_extensions import Self @@ -30,6 +31,9 @@ logger = logging.getLogger(__name__) +MIN_ORG_NAME_LENGTH = 1 +MIN_SERVER_NAME_LENGTH = 1 + @serializable() class PwdTokenResetConfig(SyftObject): @@ -237,7 +241,7 @@ class ServerSettings(SyftObject): description: str = "This is the default description for a Datasite Server." server_type: ServerType = ServerType.DATASITE signup_enabled: bool - admin_email: str + admin_email: EmailStr server_side_type: ServerSideType = ServerSideType.HIGH_SIDE show_warnings: bool association_request_auto_approval: bool @@ -250,6 +254,22 @@ class ServerSettings(SyftObject): pwd_token_config: PwdTokenResetConfig = PwdTokenResetConfig() allow_guest_sessions: bool = True + @field_validator("organization") + def organization_length(cls, v: str) -> str: + if len(v) < MIN_ORG_NAME_LENGTH: + raise ValueError( + f"'organization' must be at least {MIN_ORG_NAME_LENGTH} characters long" + ) + return v + + @field_validator("name") + def name_length(cls, v: str) -> str: + if len(v) < MIN_SERVER_NAME_LENGTH: + raise ValueError( + f'"name" must be at least {MIN_SERVER_NAME_LENGTH} characters long' + ) + return v + def _repr_html_(self) -> Any: # .api.services.notifications.settings() is how the server itself would dispatch notifications. # .api.services.notifications.user_settings() sets if a specific user wants or not to receive notifications. diff --git a/packages/syft/src/syft/service/settings/settings_service.py b/packages/syft/src/syft/service/settings/settings_service.py index e7675b9f33d..ca307ef2567 100644 --- a/packages/syft/src/syft/service/settings/settings_service.py +++ b/packages/syft/src/syft/service/settings/settings_service.py @@ -3,6 +3,9 @@ from typing import Any from typing import cast +# third party +from pydantic import ValidationError + # relative from ...abstract_server import ServerSideType from ...serde.serializable import serializable @@ -118,7 +121,7 @@ def update( value=updated_settings, ) - @as_result(StashException, NotFoundException) + @as_result(StashException, NotFoundException, ValidationError) def _update( self, context: AuthedServiceContext, settings: ServerSettingsUpdate ) -> ServerSettings: @@ -127,6 +130,7 @@ def _update( new_settings = all_settings[0].model_copy( update=settings.to_dict(exclude_empty=True) ) + ServerSettings.model_validate(new_settings.to_dict()) update_result = self.stash.update( context.credentials, settings=new_settings ).unwrap() diff --git a/tox.ini b/tox.ini index 3716fc9de44..67d86b19ff7 100644 --- a/tox.ini +++ b/tox.ini @@ -355,6 +355,8 @@ setenv = TEST_query_limit_size={env:test_query_limit_size:500000} SERVER_URL = {env:SERVER_URL:http://localhost} SERVER_PORT = {env:SERVER_PORT:8080} + NUM_TEST_USERS = {env:NUM_TEST_USERS:5} + NUM_TEST_JOBS = {env:NUM_TEST_JOBS:10} commands = python --version bash -c "echo Running with ORCHESTRA_DEPLOYMENT_TYPE=$ORCHESTRA_DEPLOYMENT_TYPE DEV_MODE=$DEV_MODE TEST_NOTEBOOK_PATHS=$TEST_NOTEBOOK_PATHS; date" @@ -422,6 +424,9 @@ setenv = TEST_EXTERNAL_REGISTRY = {env:TEST_EXTERNAL_REGISTRY:k3d-registry.localhost:5800} TEST_QUERY_LIMIT_SIZE={env:TEST_QUERY_LIMIT_SIZE:500000} TRACING={env:TRACING:False} + NUM_TEST_USERS = {env:NUM_TEST_USERS:5} + NUM_TEST_JOBS = {env:NUM_TEST_JOBS:10} + NUM_TEST_WORKERS = {env:NUM_TEST_WORKERS:2} commands = bash -c "python --version || true" bash -c "echo Running with GITHUB_CI=$GITHUB_CI; date"