From 76a928814fac6971633afa3eb79e53c79d54ca92 Mon Sep 17 00:00:00 2001 From: "ddefreitas.exe" <1959720+darrell-d@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:52:22 -0400 Subject: [PATCH 1/5] regenerate protos from pennsieve-agent Sync agent.proto with pennsieve-agent and regenerate agent_pb2.py and agent_pb2_grpc.py. Picks up Push (for map-based uploads) and Deregister (account removal), both previously missing from the Python stubs. Generated with grpcio-tools ~=1.51 / protobuf ~=4.21 to match the project's pinned versions. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/pennsieve/protos/agent.proto | 16 ++ src/pennsieve/protos/agent_pb2.py | 300 +++++++++++++------------ src/pennsieve/protos/agent_pb2_grpc.py | 66 ++++++ 3 files changed, 235 insertions(+), 147 deletions(-) diff --git a/src/pennsieve/protos/agent.proto b/src/pennsieve/protos/agent.proto index 7bbadad..2c4b216 100644 --- a/src/pennsieve/protos/agent.proto +++ b/src/pennsieve/protos/agent.proto @@ -25,6 +25,7 @@ service Agent { rpc CancelDownload(CancelDownloadRequest) returns (SimpleStatusResponse) {} rpc Map(MapRequest) returns (SimpleStatusResponse) {} rpc Pull(PullRequest) returns (SimpleStatusResponse) {} + rpc Push(PushRequest) returns (SimpleStatusResponse) {} rpc GetMapDiff(MapDiffRequest) returns (MapDiffResponse) {} // Server Endpoints @@ -47,6 +48,7 @@ service Agent { // Account Endpoints rpc Register(RegisterRequest) returns (RegisterResponse){} + rpc Deregister(DeregisterRequest) returns (DeregisterResponse){} // Timeseries Endpoints rpc GetTimeseriesChannels(GetTimeseriesChannelsRequest) returns (GetTimeseriesChannelsResponse) {} @@ -58,6 +60,10 @@ message PullRequest { string path = 1; } +message PushRequest { + string path = 1; +} + message SubscribeRequest { int32 id = 1; } @@ -395,6 +401,16 @@ message RegisterResponse{ string account_id = 1; } +message DeregisterRequest{ + Account account = 1; + Credentials credentials = 2; + bool force = 3; +} +message DeregisterResponse{ + string account_id = 1; + string role_name = 2; +} + message Account { enum AccountType { AWS = 0; diff --git a/src/pennsieve/protos/agent_pb2.py b/src/pennsieve/protos/agent_pb2.py index 7361199..1c333f9 100644 --- a/src/pennsieve/protos/agent_pb2.py +++ b/src/pennsieve/protos/agent_pb2.py @@ -14,7 +14,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cpennsieve/protos/agent.proto\x12\x02v1\"\x1b\n\x0bPullRequest\x12\x0c\n\x04path\x18\x01 \x01(\t\"\x1e\n\x10SubscribeRequest\x12\n\n\x02id\x18\x01 \x01(\x05\"+\n\x11ResetCacheRequest\x12\x0f\n\x02id\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x05\n\x03_id\"W\n\x1cGetTimeseriesChannelsRequest\x12\x12\n\ndataset_id\x18\x01 \x01(\t\x12\x12\n\npackage_id\x18\x02 \x01(\t\x12\x0f\n\x07refresh\x18\x03 \x01(\x08\"o\n\x11TimeseriesChannel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x12\n\nstart_time\x18\x03 \x01(\x04\x12\x10\n\x08\x65nd_time\x18\x04 \x01(\x04\x12\x0c\n\x04unit\x18\x05 \x01(\t\x12\x0c\n\x04rate\x18\x06 \x01(\x02\"G\n\x1dGetTimeseriesChannelsResponse\x12&\n\x07\x63hannel\x18\x01 \x03(\x0b\x32\x15.v1.TimeseriesChannel\"\xa6\x01\n\x19GetTimeseriesRangeRequest\x12\x12\n\ndataset_id\x18\x01 \x01(\t\x12\x12\n\npackage_id\x18\x02 \x01(\t\x12\x13\n\x0b\x63hannel_ids\x18\x03 \x03(\t\x12\x12\n\nstart_time\x18\x04 \x01(\x02\x12\x10\n\x08\x65nd_time\x18\x05 \x01(\x02\x12\x0f\n\x07refresh\x18\x06 \x01(\x08\x12\x15\n\rrelative_time\x18\x07 \x01(\x08\"\xa9\x04\n\x1aGetTimeseriesRangeResponse\x12\x38\n\x04type\x18\x01 \x01(\x0e\x32*.v1.GetTimeseriesRangeResponse.MessageType\x12\x39\n\x05\x65rror\x18\x02 \x01(\x0b\x32(.v1.GetTimeseriesRangeResponse.ErrorDataH\x00\x12\x38\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32(.v1.GetTimeseriesRangeResponse.RangeDataH\x00\x12=\n\x07\x63hannel\x18\x04 \x01(\x0b\x32*.v1.GetTimeseriesRangeResponse.ChannelInfoH\x00\x1aK\n\x0b\x43hannelInfo\x12\x12\n\nchannel_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0c\n\x04unit\x18\x03 \x01(\t\x12\x0c\n\x04rate\x18\x04 \x01(\x02\x1aW\n\tRangeData\x12\r\n\x05start\x18\x01 \x01(\x04\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x04\x12\x0c\n\x04rate\x18\x03 \x01(\x02\x12\x12\n\nchannel_id\x18\x04 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x05 \x03(\x02\x1a\x19\n\tErrorData\x12\x0c\n\x04info\x18\x01 \x01(\t\"L\n\x0bMessageType\x12\x10\n\x0cRANGE_STATUS\x10\x00\x12\x0e\n\nRANGE_DATA\x10\x01\x12\x10\n\x0c\x43HANNEL_INFO\x10\x02\x12\t\n\x05\x45RROR\x10\x03\x42\x0e\n\x0cmessage_data\"\xd2\x08\n\x11SubscribeResponse\x12/\n\x04type\x18\x08 \x01(\x0e\x32!.v1.SubscribeResponse.MessageType\x12=\n\rupload_status\x18\t \x01(\x0b\x32$.v1.SubscribeResponse.UploadResponseH\x00\x12\x39\n\nevent_info\x18\n \x01(\x0b\x32#.v1.SubscribeResponse.EventResponseH\x00\x12\x39\n\x0bsync_status\x18\x0b \x01(\x0b\x32\".v1.SubscribeResponse.SyncResponseH\x00\x12G\n\x0f\x64ownload_status\x18\x0c \x01(\x0b\x32,.v1.SubscribeResponse.DownloadStatusResponseH\x00\x1a \n\rEventResponse\x12\x0f\n\x07\x64\x65tails\x18\x01 \x01(\t\x1a\xd0\x01\n\x0eUploadResponse\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\r\n\x05total\x18\x02 \x01(\x03\x12\x0f\n\x07\x63urrent\x18\x03 \x01(\x03\x12\x11\n\tworker_id\x18\x04 \x01(\x05\x12\x41\n\x06status\x18\x05 \x01(\x0e\x32\x31.v1.SubscribeResponse.UploadResponse.UploadStatus\"7\n\x0cUploadStatus\x12\x08\n\x04INIT\x10\x00\x12\x0f\n\x0bIN_PROGRESS\x10\x01\x12\x0c\n\x08\x43OMPLETE\x10\x02\x1a\xd1\x01\n\x16\x44ownloadStatusResponse\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\r\n\x05total\x18\x02 \x01(\x03\x12\x0f\n\x07\x63urrent\x18\x03 \x01(\x03\x12K\n\x06status\x18\x04 \x01(\x0e\x32;.v1.SubscribeResponse.DownloadStatusResponse.DownloadStatus\"9\n\x0e\x44ownloadStatus\x12\x08\n\x04INIT\x10\x00\x12\x0f\n\x0bIN_PROGRESS\x10\x01\x12\x0c\n\x08\x43OMPLETE\x10\x02\x1a\xb9\x01\n\x0cSyncResponse\x12=\n\x06status\x18\x01 \x01(\x0e\x32-.v1.SubscribeResponse.SyncResponse.SyncStatus\x12\r\n\x05total\x18\x02 \x01(\x03\x12\x11\n\tnr_synced\x18\x03 \x01(\x03\x12\x11\n\tworker_id\x18\x04 \x01(\x05\"5\n\nSyncStatus\x12\x08\n\x04INIT\x10\x00\x12\x0f\n\x0bIN_PROGRESS\x10\x01\x12\x0c\n\x08\x43OMPLETE\x10\x02\"y\n\x0bMessageType\x12\t\n\x05\x45VENT\x10\x00\x12\x11\n\rUPLOAD_STATUS\x10\x01\x12\x11\n\rUPLOAD_CANCEL\x10\x02\x12\x0f\n\x0bSYNC_STATUS\x10\x03\x12\x13\n\x0f\x44OWNLOAD_STATUS\x10\x04\x12\x13\n\x0f\x44OWNLOAD_CANCEL\x10\x05\x42\x0e\n\x0cmessage_data\"&\n\x14SimpleStatusResponse\x12\x0e\n\x06status\x18\x01 \x01(\t\">\n\x13\x43\x61ncelUploadRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x12\n\ncancel_all\x18\x02 \x01(\x08\"C\n\x15\x43\x61ncelDownloadRequest\x12\x0f\n\x02id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x12\n\ncancel_all\x18\x02 \x01(\x08\x42\x05\n\x03_id\"f\n\x15\x43reateManifestRequest\x12\x11\n\tbase_path\x18\x01 \x01(\t\x12\x18\n\x10target_base_path\x18\x02 \x01(\t\x12\x11\n\trecursive\x18\x03 \x01(\x08\x12\r\n\x05\x66iles\x18\x04 \x03(\t\">\n\x16\x43reateManifestResponse\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x0f\n\x07message\x18\x02 \x01(\t\"z\n\x14\x41\x64\x64ToManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x11\n\tbase_path\x18\x02 \x01(\t\x12\x18\n\x10target_base_path\x18\x03 \x01(\t\x12\x11\n\trecursive\x18\x04 \x01(\x08\x12\r\n\x05\x66iles\x18\x05 \x03(\t\"E\n\x19RemoveFromManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x13\n\x0bremove_path\x18\x03 \x01(\t\"\x10\n\x0eVersionRequest\"5\n\x0fVersionResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\x11\n\tlog_level\x18\x02 \x01(\t\"\r\n\x0bPingRequest\"\x1f\n\x0cPingResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"\r\n\x0bStopRequest\"\x1f\n\x0cStopResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"\x16\n\x14ListManifestsRequest\"\x8a\x02\n\x15ListManifestsResponse\x12\x35\n\tmanifests\x18\x01 \x03(\x0b\x32\".v1.ListManifestsResponse.Manifest\x1a\xb9\x01\n\x08Manifest\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0f\n\x07node_id\x18\x02 \x01(\t\x12\x11\n\tuser_name\x18\x03 \x01(\t\x12\x0f\n\x07user_id\x18\x04 \x01(\t\x12\x19\n\x11organization_name\x18\x05 \x01(\t\x12\x17\n\x0forganization_id\x18\x06 \x01(\t\x12\x14\n\x0c\x64\x61taset_name\x18\x07 \x01(\t\x12\x12\n\ndataset_id\x18\x08 \x01(\t\x12\x0e\n\x06status\x18\t \x01(\t\",\n\x15\x44\x65leteManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\"N\n\x18ListManifestFilesRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\r\n\x05limit\x18\x03 \x01(\x05\"\x90\x03\n\x19ListManifestFilesResponse\x12\x36\n\x04\x66ile\x18\x01 \x03(\x0b\x32(.v1.ListManifestFilesResponse.FileUpload\x1a\xa4\x01\n\nFileUpload\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x13\n\x0bmanifest_id\x18\x02 \x01(\x05\x12\x13\n\x0bsource_path\x18\x03 \x01(\t\x12\x13\n\x0btarget_path\x18\x04 \x01(\t\x12\x11\n\tupload_id\x18\x05 \x01(\t\x12\x38\n\x06status\x18\x06 \x01(\x0e\x32(.v1.ListManifestFilesResponse.StatusType\"\x93\x01\n\nStatusType\x12\t\n\x05LOCAL\x10\x00\x12\x0e\n\nREGISTERED\x10\x01\x12\x0c\n\x08IMPORTED\x10\x02\x12\r\n\tFINALIZED\x10\x03\x12\x0c\n\x08VERIFIED\x10\x04\x12\n\n\x06\x46\x41ILED\x10\x05\x12\x0b\n\x07REMOVED\x10\x06\x12\x0b\n\x07UNKNOWN\x10\x07\x12\x0b\n\x07\x43HANGED\x10\x08\x12\x0c\n\x08UPLOADED\x10\t\",\n\x15UploadManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\"\x10\n\x0eGetUserRequest\"\xd4\x01\n\x0cUserResponse\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x15\n\rsession_token\x18\x04 \x01(\t\x12\x14\n\x0ctoken_expire\x18\x05 \x01(\x03\x12\x0f\n\x07profile\x18\x08 \x01(\t\x12\x13\n\x0b\x65nvironment\x18\t \x01(\t\x12\x17\n\x0forganization_id\x18\n \x01(\t\x12\x19\n\x11organization_name\x18\x0b \x01(\t\x12\x10\n\x08\x61pi_host\x18\x0c \x01(\t\x12\x11\n\tapi2_host\x18\r \x01(\t\"\'\n\x14SwitchProfileRequest\x12\x0f\n\x07profile\x18\x01 \x01(\t\"\x17\n\x15ReAuthenticateRequest\"\'\n\x11UseDatasetRequest\x12\x12\n\ndataset_id\x18\x01 \x01(\t\"(\n\x12UseDatasetResponse\x12\x12\n\ndataset_id\x18\x01 \x01(\t\"*\n\x13SyncManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\"}\n\x14SyncManifestResponse\x12\x18\n\x10manifest_node_id\x18\x01 \x01(\t\x12\x18\n\x10nr_files_updated\x18\x02 \x01(\x05\x12\x18\n\x10nr_files_removed\x18\x03 \x01(\x05\x12\x17\n\x0fnr_files_failed\x18\x04 \x01(\x05\"+\n\x14ResetManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\"W\n\x1cRelocateManifestFilesRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x0c\n\x04path\x18\x02 \x01(\t\x12\x14\n\x0cupdated_path\x18\x03 \x01(\t\"A\n\x14StartWorkflowRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x14\n\x0cworkflowFlag\x18\x02 \x01(\t\"\x96\x01\n\x10WorkflowResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x13\n\x0b\x64\x65rivatives\x18\x02 \x01(\t\x12\x37\n\x0cworkflowType\x18\x03 \x01(\x0e\x32!.v1.WorkflowResponse.WorkflowType\"#\n\x0cWorkflowType\x12\x08\n\x04PATH\x10\x00\x12\t\n\x05NAMED\x10\x01\"U\n\x0fRegisterRequest\x12\x1c\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32\x0b.v1.Account\x12$\n\x0b\x63redentials\x18\x02 \x01(\x0b\x32\x0f.v1.Credentials\"&\n\x10RegisterResponse\x12\x12\n\naccount_id\x18\x01 \x01(\t\"S\n\x07\x41\x63\x63ount\x12%\n\x04type\x18\x01 \x01(\x0e\x32\x17.v1.Account.AccountType\"!\n\x0b\x41\x63\x63ountType\x12\x07\n\x03\x41WS\x10\x00\x12\t\n\x05\x41zure\x10\x01\"\x1e\n\x0b\x43redentials\x12\x0f\n\x07profile\x18\x01 \x01(\t\"7\n\nMapRequest\x12\x12\n\ndataset_id\x18\x01 \x01(\t\x12\x15\n\rtarget_folder\x18\x02 \x01(\t\"\xd1\x01\n\x0f\x44ownloadRequest\x12.\n\x04type\x18\x01 \x01(\x0e\x32 .v1.DownloadRequest.DownloadType\x12-\n\x07\x64\x61taset\x18\t \x01(\x0b\x32\x1a.v1.DownloadDatasetRequestH\x00\x12-\n\x07package\x18\n \x01(\x0b\x32\x1a.v1.DownloadPackageRequestH\x00\"(\n\x0c\x44ownloadType\x12\x0b\n\x07PACKAGE\x10\x00\x12\x0b\n\x07\x44\x41TASET\x10\x01\x42\x06\n\x04\x64\x61ta\"C\n\x16\x44ownloadDatasetRequest\x12\x12\n\ndataset_id\x18\x01 \x01(\t\x12\x15\n\rtarget_folder\x18\x02 \x01(\t\"G\n\x16\x44ownloadPackageRequest\x12\x12\n\npackage_id\x18\x01 \x01(\t\x12\x19\n\x11get_presigned_url\x18\x02 \x01(\x08\"\x91\x01\n\x10\x44ownloadResponse\x12/\n\x04type\x18\x01 \x01(\x0e\x32!.v1.DownloadResponse.ResponseType\x12\x0e\n\x06status\x18\x02 \x01(\t\x12\x0b\n\x03url\x18\x03 \x03(\t\"/\n\x0cResponseType\x12\x11\n\rPRESIGNED_URL\x10\x00\x12\x0c\n\x08\x44OWNLOAD\x10\x01\"\x1e\n\x0eMapDiffRequest\x12\x0c\n\x04path\x18\x01 \x01(\t\"K\n\x08\x66ileInfo\x12\x12\n\npackage_id\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0f\n\x07message\x18\x04 \x01(\t\"\xbe\x01\n\rpackageStatus\x12\x1d\n\x07\x63ontent\x18\x01 \x01(\x0b\x32\x0c.v1.fileInfo\x12\x30\n\nchangeType\x18\x02 \x01(\x0e\x32\x1c.v1.packageStatus.StatusType\"\\\n\nStatusType\x12\t\n\x05\x41\x44\x44\x45\x44\x10\x00\x12\x0b\n\x07RENAMED\x10\x01\x12\x0b\n\x07\x44\x45LETED\x10\x02\x12\x0b\n\x07\x43HANGED\x10\x03\x12\t\n\x05MOVED\x10\x04\x12\x11\n\rMOVED_RENAMED\x10\x05\"3\n\x0fMapDiffResponse\x12 \n\x05\x66iles\x18\x01 \x03(\x0b\x32\x11.v1.packageStatus2\xe2\x0f\n\x05\x41gent\x12I\n\x0e\x43reateManifest\x12\x19.v1.CreateManifestRequest\x1a\x1a.v1.CreateManifestResponse\"\x00\x12\x45\n\rAddToManifest\x12\x18.v1.AddToManifestRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12O\n\x12RemoveFromManifest\x12\x1d.v1.RemoveFromManifestRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12G\n\x0e\x44\x65leteManifest\x12\x19.v1.DeleteManifestRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x46\n\rListManifests\x12\x18.v1.ListManifestsRequest\x1a\x19.v1.ListManifestsResponse\"\x00\x12R\n\x11ListManifestFiles\x12\x1c.v1.ListManifestFilesRequest\x1a\x1d.v1.ListManifestFilesResponse\"\x00\x12U\n\x15RelocateManifestFiles\x12 .v1.RelocateManifestFilesRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x43\n\x0cSyncManifest\x12\x17.v1.SyncManifestRequest\x1a\x18.v1.SyncManifestResponse\"\x00\x12\x45\n\rResetManifest\x12\x18.v1.ResetManifestRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12G\n\x0eUploadManifest\x12\x19.v1.UploadManifestRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x43\n\x0c\x43\x61ncelUpload\x12\x17.v1.CancelUploadRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x37\n\x08\x44ownload\x12\x13.v1.DownloadRequest\x1a\x14.v1.DownloadResponse\"\x00\x12G\n\x0e\x43\x61ncelDownload\x12\x19.v1.CancelDownloadRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x31\n\x03Map\x12\x0e.v1.MapRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x33\n\x04Pull\x12\x0f.v1.PullRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x37\n\nGetMapDiff\x12\x12.v1.MapDiffRequest\x1a\x13.v1.MapDiffResponse\"\x00\x12\x34\n\x07Version\x12\x12.v1.VersionRequest\x1a\x13.v1.VersionResponse\"\x00\x12<\n\tSubscribe\x12\x14.v1.SubscribeRequest\x1a\x15.v1.SubscribeResponse\"\x00\x30\x01\x12<\n\x0bUnsubscribe\x12\x14.v1.SubscribeRequest\x1a\x15.v1.SubscribeResponse\"\x00\x12+\n\x04Stop\x12\x0f.v1.StopRequest\x1a\x10.v1.StopResponse\"\x00\x12+\n\x04Ping\x12\x0f.v1.PingRequest\x1a\x10.v1.PingResponse\"\x00\x12\x31\n\x07GetUser\x12\x12.v1.GetUserRequest\x1a\x10.v1.UserResponse\"\x00\x12=\n\rSwitchProfile\x12\x18.v1.SwitchProfileRequest\x1a\x10.v1.UserResponse\"\x00\x12?\n\x0eReAuthenticate\x12\x19.v1.ReAuthenticateRequest\x1a\x10.v1.UserResponse\"\x00\x12=\n\nUseDataset\x12\x15.v1.UseDatasetRequest\x1a\x16.v1.UseDatasetResponse\"\x00\x12\x41\n\rStartWorkflow\x12\x18.v1.StartWorkflowRequest\x1a\x14.v1.WorkflowResponse\"\x00\x12\x37\n\x08Register\x12\x13.v1.RegisterRequest\x1a\x14.v1.RegisterResponse\"\x00\x12^\n\x15GetTimeseriesChannels\x12 .v1.GetTimeseriesChannelsRequest\x1a!.v1.GetTimeseriesChannelsResponse\"\x00\x12\x62\n\x1dGetTimeseriesRangeForChannels\x12\x1d.v1.GetTimeseriesRangeRequest\x1a\x1e.v1.GetTimeseriesRangeResponse\"\x00\x30\x01\x12?\n\nResetCache\x12\x15.v1.ResetCacheRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x42-Z+github.com/pennsieve/pennsieve-agent/api/v1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cpennsieve/protos/agent.proto\x12\x02v1\"\x1b\n\x0bPullRequest\x12\x0c\n\x04path\x18\x01 \x01(\t\"\x1b\n\x0bPushRequest\x12\x0c\n\x04path\x18\x01 \x01(\t\"\x1e\n\x10SubscribeRequest\x12\n\n\x02id\x18\x01 \x01(\x05\"+\n\x11ResetCacheRequest\x12\x0f\n\x02id\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x05\n\x03_id\"W\n\x1cGetTimeseriesChannelsRequest\x12\x12\n\ndataset_id\x18\x01 \x01(\t\x12\x12\n\npackage_id\x18\x02 \x01(\t\x12\x0f\n\x07refresh\x18\x03 \x01(\x08\"o\n\x11TimeseriesChannel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x12\n\nstart_time\x18\x03 \x01(\x04\x12\x10\n\x08\x65nd_time\x18\x04 \x01(\x04\x12\x0c\n\x04unit\x18\x05 \x01(\t\x12\x0c\n\x04rate\x18\x06 \x01(\x02\"G\n\x1dGetTimeseriesChannelsResponse\x12&\n\x07\x63hannel\x18\x01 \x03(\x0b\x32\x15.v1.TimeseriesChannel\"\xa6\x01\n\x19GetTimeseriesRangeRequest\x12\x12\n\ndataset_id\x18\x01 \x01(\t\x12\x12\n\npackage_id\x18\x02 \x01(\t\x12\x13\n\x0b\x63hannel_ids\x18\x03 \x03(\t\x12\x12\n\nstart_time\x18\x04 \x01(\x02\x12\x10\n\x08\x65nd_time\x18\x05 \x01(\x02\x12\x0f\n\x07refresh\x18\x06 \x01(\x08\x12\x15\n\rrelative_time\x18\x07 \x01(\x08\"\xa9\x04\n\x1aGetTimeseriesRangeResponse\x12\x38\n\x04type\x18\x01 \x01(\x0e\x32*.v1.GetTimeseriesRangeResponse.MessageType\x12\x39\n\x05\x65rror\x18\x02 \x01(\x0b\x32(.v1.GetTimeseriesRangeResponse.ErrorDataH\x00\x12\x38\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32(.v1.GetTimeseriesRangeResponse.RangeDataH\x00\x12=\n\x07\x63hannel\x18\x04 \x01(\x0b\x32*.v1.GetTimeseriesRangeResponse.ChannelInfoH\x00\x1aK\n\x0b\x43hannelInfo\x12\x12\n\nchannel_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0c\n\x04unit\x18\x03 \x01(\t\x12\x0c\n\x04rate\x18\x04 \x01(\x02\x1aW\n\tRangeData\x12\r\n\x05start\x18\x01 \x01(\x04\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x04\x12\x0c\n\x04rate\x18\x03 \x01(\x02\x12\x12\n\nchannel_id\x18\x04 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x05 \x03(\x02\x1a\x19\n\tErrorData\x12\x0c\n\x04info\x18\x01 \x01(\t\"L\n\x0bMessageType\x12\x10\n\x0cRANGE_STATUS\x10\x00\x12\x0e\n\nRANGE_DATA\x10\x01\x12\x10\n\x0c\x43HANNEL_INFO\x10\x02\x12\t\n\x05\x45RROR\x10\x03\x42\x0e\n\x0cmessage_data\"\xd2\x08\n\x11SubscribeResponse\x12/\n\x04type\x18\x08 \x01(\x0e\x32!.v1.SubscribeResponse.MessageType\x12=\n\rupload_status\x18\t \x01(\x0b\x32$.v1.SubscribeResponse.UploadResponseH\x00\x12\x39\n\nevent_info\x18\n \x01(\x0b\x32#.v1.SubscribeResponse.EventResponseH\x00\x12\x39\n\x0bsync_status\x18\x0b \x01(\x0b\x32\".v1.SubscribeResponse.SyncResponseH\x00\x12G\n\x0f\x64ownload_status\x18\x0c \x01(\x0b\x32,.v1.SubscribeResponse.DownloadStatusResponseH\x00\x1a \n\rEventResponse\x12\x0f\n\x07\x64\x65tails\x18\x01 \x01(\t\x1a\xd0\x01\n\x0eUploadResponse\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\r\n\x05total\x18\x02 \x01(\x03\x12\x0f\n\x07\x63urrent\x18\x03 \x01(\x03\x12\x11\n\tworker_id\x18\x04 \x01(\x05\x12\x41\n\x06status\x18\x05 \x01(\x0e\x32\x31.v1.SubscribeResponse.UploadResponse.UploadStatus\"7\n\x0cUploadStatus\x12\x08\n\x04INIT\x10\x00\x12\x0f\n\x0bIN_PROGRESS\x10\x01\x12\x0c\n\x08\x43OMPLETE\x10\x02\x1a\xd1\x01\n\x16\x44ownloadStatusResponse\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\r\n\x05total\x18\x02 \x01(\x03\x12\x0f\n\x07\x63urrent\x18\x03 \x01(\x03\x12K\n\x06status\x18\x04 \x01(\x0e\x32;.v1.SubscribeResponse.DownloadStatusResponse.DownloadStatus\"9\n\x0e\x44ownloadStatus\x12\x08\n\x04INIT\x10\x00\x12\x0f\n\x0bIN_PROGRESS\x10\x01\x12\x0c\n\x08\x43OMPLETE\x10\x02\x1a\xb9\x01\n\x0cSyncResponse\x12=\n\x06status\x18\x01 \x01(\x0e\x32-.v1.SubscribeResponse.SyncResponse.SyncStatus\x12\r\n\x05total\x18\x02 \x01(\x03\x12\x11\n\tnr_synced\x18\x03 \x01(\x03\x12\x11\n\tworker_id\x18\x04 \x01(\x05\"5\n\nSyncStatus\x12\x08\n\x04INIT\x10\x00\x12\x0f\n\x0bIN_PROGRESS\x10\x01\x12\x0c\n\x08\x43OMPLETE\x10\x02\"y\n\x0bMessageType\x12\t\n\x05\x45VENT\x10\x00\x12\x11\n\rUPLOAD_STATUS\x10\x01\x12\x11\n\rUPLOAD_CANCEL\x10\x02\x12\x0f\n\x0bSYNC_STATUS\x10\x03\x12\x13\n\x0f\x44OWNLOAD_STATUS\x10\x04\x12\x13\n\x0f\x44OWNLOAD_CANCEL\x10\x05\x42\x0e\n\x0cmessage_data\"&\n\x14SimpleStatusResponse\x12\x0e\n\x06status\x18\x01 \x01(\t\">\n\x13\x43\x61ncelUploadRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x12\n\ncancel_all\x18\x02 \x01(\x08\"C\n\x15\x43\x61ncelDownloadRequest\x12\x0f\n\x02id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x12\n\ncancel_all\x18\x02 \x01(\x08\x42\x05\n\x03_id\"f\n\x15\x43reateManifestRequest\x12\x11\n\tbase_path\x18\x01 \x01(\t\x12\x18\n\x10target_base_path\x18\x02 \x01(\t\x12\x11\n\trecursive\x18\x03 \x01(\x08\x12\r\n\x05\x66iles\x18\x04 \x03(\t\">\n\x16\x43reateManifestResponse\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x0f\n\x07message\x18\x02 \x01(\t\"z\n\x14\x41\x64\x64ToManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x11\n\tbase_path\x18\x02 \x01(\t\x12\x18\n\x10target_base_path\x18\x03 \x01(\t\x12\x11\n\trecursive\x18\x04 \x01(\x08\x12\r\n\x05\x66iles\x18\x05 \x03(\t\"E\n\x19RemoveFromManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x13\n\x0bremove_path\x18\x03 \x01(\t\"\x10\n\x0eVersionRequest\"5\n\x0fVersionResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\x11\n\tlog_level\x18\x02 \x01(\t\"\r\n\x0bPingRequest\"\x1f\n\x0cPingResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"\r\n\x0bStopRequest\"\x1f\n\x0cStopResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"\x16\n\x14ListManifestsRequest\"\x8a\x02\n\x15ListManifestsResponse\x12\x35\n\tmanifests\x18\x01 \x03(\x0b\x32\".v1.ListManifestsResponse.Manifest\x1a\xb9\x01\n\x08Manifest\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0f\n\x07node_id\x18\x02 \x01(\t\x12\x11\n\tuser_name\x18\x03 \x01(\t\x12\x0f\n\x07user_id\x18\x04 \x01(\t\x12\x19\n\x11organization_name\x18\x05 \x01(\t\x12\x17\n\x0forganization_id\x18\x06 \x01(\t\x12\x14\n\x0c\x64\x61taset_name\x18\x07 \x01(\t\x12\x12\n\ndataset_id\x18\x08 \x01(\t\x12\x0e\n\x06status\x18\t \x01(\t\",\n\x15\x44\x65leteManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\"N\n\x18ListManifestFilesRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\r\n\x05limit\x18\x03 \x01(\x05\"\x90\x03\n\x19ListManifestFilesResponse\x12\x36\n\x04\x66ile\x18\x01 \x03(\x0b\x32(.v1.ListManifestFilesResponse.FileUpload\x1a\xa4\x01\n\nFileUpload\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x13\n\x0bmanifest_id\x18\x02 \x01(\x05\x12\x13\n\x0bsource_path\x18\x03 \x01(\t\x12\x13\n\x0btarget_path\x18\x04 \x01(\t\x12\x11\n\tupload_id\x18\x05 \x01(\t\x12\x38\n\x06status\x18\x06 \x01(\x0e\x32(.v1.ListManifestFilesResponse.StatusType\"\x93\x01\n\nStatusType\x12\t\n\x05LOCAL\x10\x00\x12\x0e\n\nREGISTERED\x10\x01\x12\x0c\n\x08IMPORTED\x10\x02\x12\r\n\tFINALIZED\x10\x03\x12\x0c\n\x08VERIFIED\x10\x04\x12\n\n\x06\x46\x41ILED\x10\x05\x12\x0b\n\x07REMOVED\x10\x06\x12\x0b\n\x07UNKNOWN\x10\x07\x12\x0b\n\x07\x43HANGED\x10\x08\x12\x0c\n\x08UPLOADED\x10\t\",\n\x15UploadManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\"\x10\n\x0eGetUserRequest\"\xd4\x01\n\x0cUserResponse\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x15\n\rsession_token\x18\x04 \x01(\t\x12\x14\n\x0ctoken_expire\x18\x05 \x01(\x03\x12\x0f\n\x07profile\x18\x08 \x01(\t\x12\x13\n\x0b\x65nvironment\x18\t \x01(\t\x12\x17\n\x0forganization_id\x18\n \x01(\t\x12\x19\n\x11organization_name\x18\x0b \x01(\t\x12\x10\n\x08\x61pi_host\x18\x0c \x01(\t\x12\x11\n\tapi2_host\x18\r \x01(\t\"\'\n\x14SwitchProfileRequest\x12\x0f\n\x07profile\x18\x01 \x01(\t\"\x17\n\x15ReAuthenticateRequest\"\'\n\x11UseDatasetRequest\x12\x12\n\ndataset_id\x18\x01 \x01(\t\"(\n\x12UseDatasetResponse\x12\x12\n\ndataset_id\x18\x01 \x01(\t\"*\n\x13SyncManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\"}\n\x14SyncManifestResponse\x12\x18\n\x10manifest_node_id\x18\x01 \x01(\t\x12\x18\n\x10nr_files_updated\x18\x02 \x01(\x05\x12\x18\n\x10nr_files_removed\x18\x03 \x01(\x05\x12\x17\n\x0fnr_files_failed\x18\x04 \x01(\x05\"+\n\x14ResetManifestRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\"W\n\x1cRelocateManifestFilesRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x0c\n\x04path\x18\x02 \x01(\t\x12\x14\n\x0cupdated_path\x18\x03 \x01(\t\"A\n\x14StartWorkflowRequest\x12\x13\n\x0bmanifest_id\x18\x01 \x01(\x05\x12\x14\n\x0cworkflowFlag\x18\x02 \x01(\t\"\x96\x01\n\x10WorkflowResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x13\n\x0b\x64\x65rivatives\x18\x02 \x01(\t\x12\x37\n\x0cworkflowType\x18\x03 \x01(\x0e\x32!.v1.WorkflowResponse.WorkflowType\"#\n\x0cWorkflowType\x12\x08\n\x04PATH\x10\x00\x12\t\n\x05NAMED\x10\x01\"U\n\x0fRegisterRequest\x12\x1c\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32\x0b.v1.Account\x12$\n\x0b\x63redentials\x18\x02 \x01(\x0b\x32\x0f.v1.Credentials\"&\n\x10RegisterResponse\x12\x12\n\naccount_id\x18\x01 \x01(\t\"f\n\x11\x44\x65registerRequest\x12\x1c\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32\x0b.v1.Account\x12$\n\x0b\x63redentials\x18\x02 \x01(\x0b\x32\x0f.v1.Credentials\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\";\n\x12\x44\x65registerResponse\x12\x12\n\naccount_id\x18\x01 \x01(\t\x12\x11\n\trole_name\x18\x02 \x01(\t\"S\n\x07\x41\x63\x63ount\x12%\n\x04type\x18\x01 \x01(\x0e\x32\x17.v1.Account.AccountType\"!\n\x0b\x41\x63\x63ountType\x12\x07\n\x03\x41WS\x10\x00\x12\t\n\x05\x41zure\x10\x01\"\x1e\n\x0b\x43redentials\x12\x0f\n\x07profile\x18\x01 \x01(\t\"7\n\nMapRequest\x12\x12\n\ndataset_id\x18\x01 \x01(\t\x12\x15\n\rtarget_folder\x18\x02 \x01(\t\"\xd1\x01\n\x0f\x44ownloadRequest\x12.\n\x04type\x18\x01 \x01(\x0e\x32 .v1.DownloadRequest.DownloadType\x12-\n\x07\x64\x61taset\x18\t \x01(\x0b\x32\x1a.v1.DownloadDatasetRequestH\x00\x12-\n\x07package\x18\n \x01(\x0b\x32\x1a.v1.DownloadPackageRequestH\x00\"(\n\x0c\x44ownloadType\x12\x0b\n\x07PACKAGE\x10\x00\x12\x0b\n\x07\x44\x41TASET\x10\x01\x42\x06\n\x04\x64\x61ta\"C\n\x16\x44ownloadDatasetRequest\x12\x12\n\ndataset_id\x18\x01 \x01(\t\x12\x15\n\rtarget_folder\x18\x02 \x01(\t\"G\n\x16\x44ownloadPackageRequest\x12\x12\n\npackage_id\x18\x01 \x01(\t\x12\x19\n\x11get_presigned_url\x18\x02 \x01(\x08\"\x91\x01\n\x10\x44ownloadResponse\x12/\n\x04type\x18\x01 \x01(\x0e\x32!.v1.DownloadResponse.ResponseType\x12\x0e\n\x06status\x18\x02 \x01(\t\x12\x0b\n\x03url\x18\x03 \x03(\t\"/\n\x0cResponseType\x12\x11\n\rPRESIGNED_URL\x10\x00\x12\x0c\n\x08\x44OWNLOAD\x10\x01\"\x1e\n\x0eMapDiffRequest\x12\x0c\n\x04path\x18\x01 \x01(\t\"K\n\x08\x66ileInfo\x12\x12\n\npackage_id\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0f\n\x07message\x18\x04 \x01(\t\"\xbe\x01\n\rpackageStatus\x12\x1d\n\x07\x63ontent\x18\x01 \x01(\x0b\x32\x0c.v1.fileInfo\x12\x30\n\nchangeType\x18\x02 \x01(\x0e\x32\x1c.v1.packageStatus.StatusType\"\\\n\nStatusType\x12\t\n\x05\x41\x44\x44\x45\x44\x10\x00\x12\x0b\n\x07RENAMED\x10\x01\x12\x0b\n\x07\x44\x45LETED\x10\x02\x12\x0b\n\x07\x43HANGED\x10\x03\x12\t\n\x05MOVED\x10\x04\x12\x11\n\rMOVED_RENAMED\x10\x05\"3\n\x0fMapDiffResponse\x12 \n\x05\x66iles\x18\x01 \x03(\x0b\x32\x11.v1.packageStatus2\xd6\x10\n\x05\x41gent\x12I\n\x0e\x43reateManifest\x12\x19.v1.CreateManifestRequest\x1a\x1a.v1.CreateManifestResponse\"\x00\x12\x45\n\rAddToManifest\x12\x18.v1.AddToManifestRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12O\n\x12RemoveFromManifest\x12\x1d.v1.RemoveFromManifestRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12G\n\x0e\x44\x65leteManifest\x12\x19.v1.DeleteManifestRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x46\n\rListManifests\x12\x18.v1.ListManifestsRequest\x1a\x19.v1.ListManifestsResponse\"\x00\x12R\n\x11ListManifestFiles\x12\x1c.v1.ListManifestFilesRequest\x1a\x1d.v1.ListManifestFilesResponse\"\x00\x12U\n\x15RelocateManifestFiles\x12 .v1.RelocateManifestFilesRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x43\n\x0cSyncManifest\x12\x17.v1.SyncManifestRequest\x1a\x18.v1.SyncManifestResponse\"\x00\x12\x45\n\rResetManifest\x12\x18.v1.ResetManifestRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12G\n\x0eUploadManifest\x12\x19.v1.UploadManifestRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x43\n\x0c\x43\x61ncelUpload\x12\x17.v1.CancelUploadRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x37\n\x08\x44ownload\x12\x13.v1.DownloadRequest\x1a\x14.v1.DownloadResponse\"\x00\x12G\n\x0e\x43\x61ncelDownload\x12\x19.v1.CancelDownloadRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x31\n\x03Map\x12\x0e.v1.MapRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x33\n\x04Pull\x12\x0f.v1.PullRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x33\n\x04Push\x12\x0f.v1.PushRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x12\x37\n\nGetMapDiff\x12\x12.v1.MapDiffRequest\x1a\x13.v1.MapDiffResponse\"\x00\x12\x34\n\x07Version\x12\x12.v1.VersionRequest\x1a\x13.v1.VersionResponse\"\x00\x12<\n\tSubscribe\x12\x14.v1.SubscribeRequest\x1a\x15.v1.SubscribeResponse\"\x00\x30\x01\x12<\n\x0bUnsubscribe\x12\x14.v1.SubscribeRequest\x1a\x15.v1.SubscribeResponse\"\x00\x12+\n\x04Stop\x12\x0f.v1.StopRequest\x1a\x10.v1.StopResponse\"\x00\x12+\n\x04Ping\x12\x0f.v1.PingRequest\x1a\x10.v1.PingResponse\"\x00\x12\x31\n\x07GetUser\x12\x12.v1.GetUserRequest\x1a\x10.v1.UserResponse\"\x00\x12=\n\rSwitchProfile\x12\x18.v1.SwitchProfileRequest\x1a\x10.v1.UserResponse\"\x00\x12?\n\x0eReAuthenticate\x12\x19.v1.ReAuthenticateRequest\x1a\x10.v1.UserResponse\"\x00\x12=\n\nUseDataset\x12\x15.v1.UseDatasetRequest\x1a\x16.v1.UseDatasetResponse\"\x00\x12\x41\n\rStartWorkflow\x12\x18.v1.StartWorkflowRequest\x1a\x14.v1.WorkflowResponse\"\x00\x12\x37\n\x08Register\x12\x13.v1.RegisterRequest\x1a\x14.v1.RegisterResponse\"\x00\x12=\n\nDeregister\x12\x15.v1.DeregisterRequest\x1a\x16.v1.DeregisterResponse\"\x00\x12^\n\x15GetTimeseriesChannels\x12 .v1.GetTimeseriesChannelsRequest\x1a!.v1.GetTimeseriesChannelsResponse\"\x00\x12\x62\n\x1dGetTimeseriesRangeForChannels\x12\x1d.v1.GetTimeseriesRangeRequest\x1a\x1e.v1.GetTimeseriesRangeResponse\"\x00\x30\x01\x12?\n\nResetCache\x12\x15.v1.ResetCacheRequest\x1a\x18.v1.SimpleStatusResponse\"\x00\x42-Z+github.com/pennsieve/pennsieve-agent/api/v1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -24,150 +24,156 @@ _globals['DESCRIPTOR']._serialized_options = b'Z+github.com/pennsieve/pennsieve-agent/api/v1' _globals['_PULLREQUEST']._serialized_start=36 _globals['_PULLREQUEST']._serialized_end=63 - _globals['_SUBSCRIBEREQUEST']._serialized_start=65 - _globals['_SUBSCRIBEREQUEST']._serialized_end=95 - _globals['_RESETCACHEREQUEST']._serialized_start=97 - _globals['_RESETCACHEREQUEST']._serialized_end=140 - _globals['_GETTIMESERIESCHANNELSREQUEST']._serialized_start=142 - _globals['_GETTIMESERIESCHANNELSREQUEST']._serialized_end=229 - _globals['_TIMESERIESCHANNEL']._serialized_start=231 - _globals['_TIMESERIESCHANNEL']._serialized_end=342 - _globals['_GETTIMESERIESCHANNELSRESPONSE']._serialized_start=344 - _globals['_GETTIMESERIESCHANNELSRESPONSE']._serialized_end=415 - _globals['_GETTIMESERIESRANGEREQUEST']._serialized_start=418 - _globals['_GETTIMESERIESRANGEREQUEST']._serialized_end=584 - _globals['_GETTIMESERIESRANGERESPONSE']._serialized_start=587 - _globals['_GETTIMESERIESRANGERESPONSE']._serialized_end=1140 - _globals['_GETTIMESERIESRANGERESPONSE_CHANNELINFO']._serialized_start=855 - _globals['_GETTIMESERIESRANGERESPONSE_CHANNELINFO']._serialized_end=930 - _globals['_GETTIMESERIESRANGERESPONSE_RANGEDATA']._serialized_start=932 - _globals['_GETTIMESERIESRANGERESPONSE_RANGEDATA']._serialized_end=1019 - _globals['_GETTIMESERIESRANGERESPONSE_ERRORDATA']._serialized_start=1021 - _globals['_GETTIMESERIESRANGERESPONSE_ERRORDATA']._serialized_end=1046 - _globals['_GETTIMESERIESRANGERESPONSE_MESSAGETYPE']._serialized_start=1048 - _globals['_GETTIMESERIESRANGERESPONSE_MESSAGETYPE']._serialized_end=1124 - _globals['_SUBSCRIBERESPONSE']._serialized_start=1143 - _globals['_SUBSCRIBERESPONSE']._serialized_end=2249 - _globals['_SUBSCRIBERESPONSE_EVENTRESPONSE']._serialized_start=1467 - _globals['_SUBSCRIBERESPONSE_EVENTRESPONSE']._serialized_end=1499 - _globals['_SUBSCRIBERESPONSE_UPLOADRESPONSE']._serialized_start=1502 - _globals['_SUBSCRIBERESPONSE_UPLOADRESPONSE']._serialized_end=1710 - _globals['_SUBSCRIBERESPONSE_UPLOADRESPONSE_UPLOADSTATUS']._serialized_start=1655 - _globals['_SUBSCRIBERESPONSE_UPLOADRESPONSE_UPLOADSTATUS']._serialized_end=1710 - _globals['_SUBSCRIBERESPONSE_DOWNLOADSTATUSRESPONSE']._serialized_start=1713 - _globals['_SUBSCRIBERESPONSE_DOWNLOADSTATUSRESPONSE']._serialized_end=1922 - _globals['_SUBSCRIBERESPONSE_DOWNLOADSTATUSRESPONSE_DOWNLOADSTATUS']._serialized_start=1865 - _globals['_SUBSCRIBERESPONSE_DOWNLOADSTATUSRESPONSE_DOWNLOADSTATUS']._serialized_end=1922 - _globals['_SUBSCRIBERESPONSE_SYNCRESPONSE']._serialized_start=1925 - _globals['_SUBSCRIBERESPONSE_SYNCRESPONSE']._serialized_end=2110 - _globals['_SUBSCRIBERESPONSE_SYNCRESPONSE_SYNCSTATUS']._serialized_start=2057 - _globals['_SUBSCRIBERESPONSE_SYNCRESPONSE_SYNCSTATUS']._serialized_end=2110 - _globals['_SUBSCRIBERESPONSE_MESSAGETYPE']._serialized_start=2112 - _globals['_SUBSCRIBERESPONSE_MESSAGETYPE']._serialized_end=2233 - _globals['_SIMPLESTATUSRESPONSE']._serialized_start=2251 - _globals['_SIMPLESTATUSRESPONSE']._serialized_end=2289 - _globals['_CANCELUPLOADREQUEST']._serialized_start=2291 - _globals['_CANCELUPLOADREQUEST']._serialized_end=2353 - _globals['_CANCELDOWNLOADREQUEST']._serialized_start=2355 - _globals['_CANCELDOWNLOADREQUEST']._serialized_end=2422 - _globals['_CREATEMANIFESTREQUEST']._serialized_start=2424 - _globals['_CREATEMANIFESTREQUEST']._serialized_end=2526 - _globals['_CREATEMANIFESTRESPONSE']._serialized_start=2528 - _globals['_CREATEMANIFESTRESPONSE']._serialized_end=2590 - _globals['_ADDTOMANIFESTREQUEST']._serialized_start=2592 - _globals['_ADDTOMANIFESTREQUEST']._serialized_end=2714 - _globals['_REMOVEFROMMANIFESTREQUEST']._serialized_start=2716 - _globals['_REMOVEFROMMANIFESTREQUEST']._serialized_end=2785 - _globals['_VERSIONREQUEST']._serialized_start=2787 - _globals['_VERSIONREQUEST']._serialized_end=2803 - _globals['_VERSIONRESPONSE']._serialized_start=2805 - _globals['_VERSIONRESPONSE']._serialized_end=2858 - _globals['_PINGREQUEST']._serialized_start=2860 - _globals['_PINGREQUEST']._serialized_end=2873 - _globals['_PINGRESPONSE']._serialized_start=2875 - _globals['_PINGRESPONSE']._serialized_end=2906 - _globals['_STOPREQUEST']._serialized_start=2908 - _globals['_STOPREQUEST']._serialized_end=2921 - _globals['_STOPRESPONSE']._serialized_start=2923 - _globals['_STOPRESPONSE']._serialized_end=2954 - _globals['_LISTMANIFESTSREQUEST']._serialized_start=2956 - _globals['_LISTMANIFESTSREQUEST']._serialized_end=2978 - _globals['_LISTMANIFESTSRESPONSE']._serialized_start=2981 - _globals['_LISTMANIFESTSRESPONSE']._serialized_end=3247 - _globals['_LISTMANIFESTSRESPONSE_MANIFEST']._serialized_start=3062 - _globals['_LISTMANIFESTSRESPONSE_MANIFEST']._serialized_end=3247 - _globals['_DELETEMANIFESTREQUEST']._serialized_start=3249 - _globals['_DELETEMANIFESTREQUEST']._serialized_end=3293 - _globals['_LISTMANIFESTFILESREQUEST']._serialized_start=3295 - _globals['_LISTMANIFESTFILESREQUEST']._serialized_end=3373 - _globals['_LISTMANIFESTFILESRESPONSE']._serialized_start=3376 - _globals['_LISTMANIFESTFILESRESPONSE']._serialized_end=3776 - _globals['_LISTMANIFESTFILESRESPONSE_FILEUPLOAD']._serialized_start=3462 - _globals['_LISTMANIFESTFILESRESPONSE_FILEUPLOAD']._serialized_end=3626 - _globals['_LISTMANIFESTFILESRESPONSE_STATUSTYPE']._serialized_start=3629 - _globals['_LISTMANIFESTFILESRESPONSE_STATUSTYPE']._serialized_end=3776 - _globals['_UPLOADMANIFESTREQUEST']._serialized_start=3778 - _globals['_UPLOADMANIFESTREQUEST']._serialized_end=3822 - _globals['_GETUSERREQUEST']._serialized_start=3824 - _globals['_GETUSERREQUEST']._serialized_end=3840 - _globals['_USERRESPONSE']._serialized_start=3843 - _globals['_USERRESPONSE']._serialized_end=4055 - _globals['_SWITCHPROFILEREQUEST']._serialized_start=4057 - _globals['_SWITCHPROFILEREQUEST']._serialized_end=4096 - _globals['_REAUTHENTICATEREQUEST']._serialized_start=4098 - _globals['_REAUTHENTICATEREQUEST']._serialized_end=4121 - _globals['_USEDATASETREQUEST']._serialized_start=4123 - _globals['_USEDATASETREQUEST']._serialized_end=4162 - _globals['_USEDATASETRESPONSE']._serialized_start=4164 - _globals['_USEDATASETRESPONSE']._serialized_end=4204 - _globals['_SYNCMANIFESTREQUEST']._serialized_start=4206 - _globals['_SYNCMANIFESTREQUEST']._serialized_end=4248 - _globals['_SYNCMANIFESTRESPONSE']._serialized_start=4250 - _globals['_SYNCMANIFESTRESPONSE']._serialized_end=4375 - _globals['_RESETMANIFESTREQUEST']._serialized_start=4377 - _globals['_RESETMANIFESTREQUEST']._serialized_end=4420 - _globals['_RELOCATEMANIFESTFILESREQUEST']._serialized_start=4422 - _globals['_RELOCATEMANIFESTFILESREQUEST']._serialized_end=4509 - _globals['_STARTWORKFLOWREQUEST']._serialized_start=4511 - _globals['_STARTWORKFLOWREQUEST']._serialized_end=4576 - _globals['_WORKFLOWRESPONSE']._serialized_start=4579 - _globals['_WORKFLOWRESPONSE']._serialized_end=4729 - _globals['_WORKFLOWRESPONSE_WORKFLOWTYPE']._serialized_start=4694 - _globals['_WORKFLOWRESPONSE_WORKFLOWTYPE']._serialized_end=4729 - _globals['_REGISTERREQUEST']._serialized_start=4731 - _globals['_REGISTERREQUEST']._serialized_end=4816 - _globals['_REGISTERRESPONSE']._serialized_start=4818 - _globals['_REGISTERRESPONSE']._serialized_end=4856 - _globals['_ACCOUNT']._serialized_start=4858 - _globals['_ACCOUNT']._serialized_end=4941 - _globals['_ACCOUNT_ACCOUNTTYPE']._serialized_start=4908 - _globals['_ACCOUNT_ACCOUNTTYPE']._serialized_end=4941 - _globals['_CREDENTIALS']._serialized_start=4943 - _globals['_CREDENTIALS']._serialized_end=4973 - _globals['_MAPREQUEST']._serialized_start=4975 - _globals['_MAPREQUEST']._serialized_end=5030 - _globals['_DOWNLOADREQUEST']._serialized_start=5033 - _globals['_DOWNLOADREQUEST']._serialized_end=5242 - _globals['_DOWNLOADREQUEST_DOWNLOADTYPE']._serialized_start=5194 - _globals['_DOWNLOADREQUEST_DOWNLOADTYPE']._serialized_end=5234 - _globals['_DOWNLOADDATASETREQUEST']._serialized_start=5244 - _globals['_DOWNLOADDATASETREQUEST']._serialized_end=5311 - _globals['_DOWNLOADPACKAGEREQUEST']._serialized_start=5313 - _globals['_DOWNLOADPACKAGEREQUEST']._serialized_end=5384 - _globals['_DOWNLOADRESPONSE']._serialized_start=5387 - _globals['_DOWNLOADRESPONSE']._serialized_end=5532 - _globals['_DOWNLOADRESPONSE_RESPONSETYPE']._serialized_start=5485 - _globals['_DOWNLOADRESPONSE_RESPONSETYPE']._serialized_end=5532 - _globals['_MAPDIFFREQUEST']._serialized_start=5534 - _globals['_MAPDIFFREQUEST']._serialized_end=5564 - _globals['_FILEINFO']._serialized_start=5566 - _globals['_FILEINFO']._serialized_end=5641 - _globals['_PACKAGESTATUS']._serialized_start=5644 - _globals['_PACKAGESTATUS']._serialized_end=5834 - _globals['_PACKAGESTATUS_STATUSTYPE']._serialized_start=5742 - _globals['_PACKAGESTATUS_STATUSTYPE']._serialized_end=5834 - _globals['_MAPDIFFRESPONSE']._serialized_start=5836 - _globals['_MAPDIFFRESPONSE']._serialized_end=5887 - _globals['_AGENT']._serialized_start=5890 - _globals['_AGENT']._serialized_end=7908 + _globals['_PUSHREQUEST']._serialized_start=65 + _globals['_PUSHREQUEST']._serialized_end=92 + _globals['_SUBSCRIBEREQUEST']._serialized_start=94 + _globals['_SUBSCRIBEREQUEST']._serialized_end=124 + _globals['_RESETCACHEREQUEST']._serialized_start=126 + _globals['_RESETCACHEREQUEST']._serialized_end=169 + _globals['_GETTIMESERIESCHANNELSREQUEST']._serialized_start=171 + _globals['_GETTIMESERIESCHANNELSREQUEST']._serialized_end=258 + _globals['_TIMESERIESCHANNEL']._serialized_start=260 + _globals['_TIMESERIESCHANNEL']._serialized_end=371 + _globals['_GETTIMESERIESCHANNELSRESPONSE']._serialized_start=373 + _globals['_GETTIMESERIESCHANNELSRESPONSE']._serialized_end=444 + _globals['_GETTIMESERIESRANGEREQUEST']._serialized_start=447 + _globals['_GETTIMESERIESRANGEREQUEST']._serialized_end=613 + _globals['_GETTIMESERIESRANGERESPONSE']._serialized_start=616 + _globals['_GETTIMESERIESRANGERESPONSE']._serialized_end=1169 + _globals['_GETTIMESERIESRANGERESPONSE_CHANNELINFO']._serialized_start=884 + _globals['_GETTIMESERIESRANGERESPONSE_CHANNELINFO']._serialized_end=959 + _globals['_GETTIMESERIESRANGERESPONSE_RANGEDATA']._serialized_start=961 + _globals['_GETTIMESERIESRANGERESPONSE_RANGEDATA']._serialized_end=1048 + _globals['_GETTIMESERIESRANGERESPONSE_ERRORDATA']._serialized_start=1050 + _globals['_GETTIMESERIESRANGERESPONSE_ERRORDATA']._serialized_end=1075 + _globals['_GETTIMESERIESRANGERESPONSE_MESSAGETYPE']._serialized_start=1077 + _globals['_GETTIMESERIESRANGERESPONSE_MESSAGETYPE']._serialized_end=1153 + _globals['_SUBSCRIBERESPONSE']._serialized_start=1172 + _globals['_SUBSCRIBERESPONSE']._serialized_end=2278 + _globals['_SUBSCRIBERESPONSE_EVENTRESPONSE']._serialized_start=1496 + _globals['_SUBSCRIBERESPONSE_EVENTRESPONSE']._serialized_end=1528 + _globals['_SUBSCRIBERESPONSE_UPLOADRESPONSE']._serialized_start=1531 + _globals['_SUBSCRIBERESPONSE_UPLOADRESPONSE']._serialized_end=1739 + _globals['_SUBSCRIBERESPONSE_UPLOADRESPONSE_UPLOADSTATUS']._serialized_start=1684 + _globals['_SUBSCRIBERESPONSE_UPLOADRESPONSE_UPLOADSTATUS']._serialized_end=1739 + _globals['_SUBSCRIBERESPONSE_DOWNLOADSTATUSRESPONSE']._serialized_start=1742 + _globals['_SUBSCRIBERESPONSE_DOWNLOADSTATUSRESPONSE']._serialized_end=1951 + _globals['_SUBSCRIBERESPONSE_DOWNLOADSTATUSRESPONSE_DOWNLOADSTATUS']._serialized_start=1894 + _globals['_SUBSCRIBERESPONSE_DOWNLOADSTATUSRESPONSE_DOWNLOADSTATUS']._serialized_end=1951 + _globals['_SUBSCRIBERESPONSE_SYNCRESPONSE']._serialized_start=1954 + _globals['_SUBSCRIBERESPONSE_SYNCRESPONSE']._serialized_end=2139 + _globals['_SUBSCRIBERESPONSE_SYNCRESPONSE_SYNCSTATUS']._serialized_start=2086 + _globals['_SUBSCRIBERESPONSE_SYNCRESPONSE_SYNCSTATUS']._serialized_end=2139 + _globals['_SUBSCRIBERESPONSE_MESSAGETYPE']._serialized_start=2141 + _globals['_SUBSCRIBERESPONSE_MESSAGETYPE']._serialized_end=2262 + _globals['_SIMPLESTATUSRESPONSE']._serialized_start=2280 + _globals['_SIMPLESTATUSRESPONSE']._serialized_end=2318 + _globals['_CANCELUPLOADREQUEST']._serialized_start=2320 + _globals['_CANCELUPLOADREQUEST']._serialized_end=2382 + _globals['_CANCELDOWNLOADREQUEST']._serialized_start=2384 + _globals['_CANCELDOWNLOADREQUEST']._serialized_end=2451 + _globals['_CREATEMANIFESTREQUEST']._serialized_start=2453 + _globals['_CREATEMANIFESTREQUEST']._serialized_end=2555 + _globals['_CREATEMANIFESTRESPONSE']._serialized_start=2557 + _globals['_CREATEMANIFESTRESPONSE']._serialized_end=2619 + _globals['_ADDTOMANIFESTREQUEST']._serialized_start=2621 + _globals['_ADDTOMANIFESTREQUEST']._serialized_end=2743 + _globals['_REMOVEFROMMANIFESTREQUEST']._serialized_start=2745 + _globals['_REMOVEFROMMANIFESTREQUEST']._serialized_end=2814 + _globals['_VERSIONREQUEST']._serialized_start=2816 + _globals['_VERSIONREQUEST']._serialized_end=2832 + _globals['_VERSIONRESPONSE']._serialized_start=2834 + _globals['_VERSIONRESPONSE']._serialized_end=2887 + _globals['_PINGREQUEST']._serialized_start=2889 + _globals['_PINGREQUEST']._serialized_end=2902 + _globals['_PINGRESPONSE']._serialized_start=2904 + _globals['_PINGRESPONSE']._serialized_end=2935 + _globals['_STOPREQUEST']._serialized_start=2937 + _globals['_STOPREQUEST']._serialized_end=2950 + _globals['_STOPRESPONSE']._serialized_start=2952 + _globals['_STOPRESPONSE']._serialized_end=2983 + _globals['_LISTMANIFESTSREQUEST']._serialized_start=2985 + _globals['_LISTMANIFESTSREQUEST']._serialized_end=3007 + _globals['_LISTMANIFESTSRESPONSE']._serialized_start=3010 + _globals['_LISTMANIFESTSRESPONSE']._serialized_end=3276 + _globals['_LISTMANIFESTSRESPONSE_MANIFEST']._serialized_start=3091 + _globals['_LISTMANIFESTSRESPONSE_MANIFEST']._serialized_end=3276 + _globals['_DELETEMANIFESTREQUEST']._serialized_start=3278 + _globals['_DELETEMANIFESTREQUEST']._serialized_end=3322 + _globals['_LISTMANIFESTFILESREQUEST']._serialized_start=3324 + _globals['_LISTMANIFESTFILESREQUEST']._serialized_end=3402 + _globals['_LISTMANIFESTFILESRESPONSE']._serialized_start=3405 + _globals['_LISTMANIFESTFILESRESPONSE']._serialized_end=3805 + _globals['_LISTMANIFESTFILESRESPONSE_FILEUPLOAD']._serialized_start=3491 + _globals['_LISTMANIFESTFILESRESPONSE_FILEUPLOAD']._serialized_end=3655 + _globals['_LISTMANIFESTFILESRESPONSE_STATUSTYPE']._serialized_start=3658 + _globals['_LISTMANIFESTFILESRESPONSE_STATUSTYPE']._serialized_end=3805 + _globals['_UPLOADMANIFESTREQUEST']._serialized_start=3807 + _globals['_UPLOADMANIFESTREQUEST']._serialized_end=3851 + _globals['_GETUSERREQUEST']._serialized_start=3853 + _globals['_GETUSERREQUEST']._serialized_end=3869 + _globals['_USERRESPONSE']._serialized_start=3872 + _globals['_USERRESPONSE']._serialized_end=4084 + _globals['_SWITCHPROFILEREQUEST']._serialized_start=4086 + _globals['_SWITCHPROFILEREQUEST']._serialized_end=4125 + _globals['_REAUTHENTICATEREQUEST']._serialized_start=4127 + _globals['_REAUTHENTICATEREQUEST']._serialized_end=4150 + _globals['_USEDATASETREQUEST']._serialized_start=4152 + _globals['_USEDATASETREQUEST']._serialized_end=4191 + _globals['_USEDATASETRESPONSE']._serialized_start=4193 + _globals['_USEDATASETRESPONSE']._serialized_end=4233 + _globals['_SYNCMANIFESTREQUEST']._serialized_start=4235 + _globals['_SYNCMANIFESTREQUEST']._serialized_end=4277 + _globals['_SYNCMANIFESTRESPONSE']._serialized_start=4279 + _globals['_SYNCMANIFESTRESPONSE']._serialized_end=4404 + _globals['_RESETMANIFESTREQUEST']._serialized_start=4406 + _globals['_RESETMANIFESTREQUEST']._serialized_end=4449 + _globals['_RELOCATEMANIFESTFILESREQUEST']._serialized_start=4451 + _globals['_RELOCATEMANIFESTFILESREQUEST']._serialized_end=4538 + _globals['_STARTWORKFLOWREQUEST']._serialized_start=4540 + _globals['_STARTWORKFLOWREQUEST']._serialized_end=4605 + _globals['_WORKFLOWRESPONSE']._serialized_start=4608 + _globals['_WORKFLOWRESPONSE']._serialized_end=4758 + _globals['_WORKFLOWRESPONSE_WORKFLOWTYPE']._serialized_start=4723 + _globals['_WORKFLOWRESPONSE_WORKFLOWTYPE']._serialized_end=4758 + _globals['_REGISTERREQUEST']._serialized_start=4760 + _globals['_REGISTERREQUEST']._serialized_end=4845 + _globals['_REGISTERRESPONSE']._serialized_start=4847 + _globals['_REGISTERRESPONSE']._serialized_end=4885 + _globals['_DEREGISTERREQUEST']._serialized_start=4887 + _globals['_DEREGISTERREQUEST']._serialized_end=4989 + _globals['_DEREGISTERRESPONSE']._serialized_start=4991 + _globals['_DEREGISTERRESPONSE']._serialized_end=5050 + _globals['_ACCOUNT']._serialized_start=5052 + _globals['_ACCOUNT']._serialized_end=5135 + _globals['_ACCOUNT_ACCOUNTTYPE']._serialized_start=5102 + _globals['_ACCOUNT_ACCOUNTTYPE']._serialized_end=5135 + _globals['_CREDENTIALS']._serialized_start=5137 + _globals['_CREDENTIALS']._serialized_end=5167 + _globals['_MAPREQUEST']._serialized_start=5169 + _globals['_MAPREQUEST']._serialized_end=5224 + _globals['_DOWNLOADREQUEST']._serialized_start=5227 + _globals['_DOWNLOADREQUEST']._serialized_end=5436 + _globals['_DOWNLOADREQUEST_DOWNLOADTYPE']._serialized_start=5388 + _globals['_DOWNLOADREQUEST_DOWNLOADTYPE']._serialized_end=5428 + _globals['_DOWNLOADDATASETREQUEST']._serialized_start=5438 + _globals['_DOWNLOADDATASETREQUEST']._serialized_end=5505 + _globals['_DOWNLOADPACKAGEREQUEST']._serialized_start=5507 + _globals['_DOWNLOADPACKAGEREQUEST']._serialized_end=5578 + _globals['_DOWNLOADRESPONSE']._serialized_start=5581 + _globals['_DOWNLOADRESPONSE']._serialized_end=5726 + _globals['_DOWNLOADRESPONSE_RESPONSETYPE']._serialized_start=5679 + _globals['_DOWNLOADRESPONSE_RESPONSETYPE']._serialized_end=5726 + _globals['_MAPDIFFREQUEST']._serialized_start=5728 + _globals['_MAPDIFFREQUEST']._serialized_end=5758 + _globals['_FILEINFO']._serialized_start=5760 + _globals['_FILEINFO']._serialized_end=5835 + _globals['_PACKAGESTATUS']._serialized_start=5838 + _globals['_PACKAGESTATUS']._serialized_end=6028 + _globals['_PACKAGESTATUS_STATUSTYPE']._serialized_start=5936 + _globals['_PACKAGESTATUS_STATUSTYPE']._serialized_end=6028 + _globals['_MAPDIFFRESPONSE']._serialized_start=6030 + _globals['_MAPDIFFRESPONSE']._serialized_end=6081 + _globals['_AGENT']._serialized_start=6084 + _globals['_AGENT']._serialized_end=8218 # @@protoc_insertion_point(module_scope) diff --git a/src/pennsieve/protos/agent_pb2_grpc.py b/src/pennsieve/protos/agent_pb2_grpc.py index 4e87fe8..6816ac6 100644 --- a/src/pennsieve/protos/agent_pb2_grpc.py +++ b/src/pennsieve/protos/agent_pb2_grpc.py @@ -89,6 +89,11 @@ def __init__(self, channel): request_serializer=pennsieve_dot_protos_dot_agent__pb2.PullRequest.SerializeToString, response_deserializer=pennsieve_dot_protos_dot_agent__pb2.SimpleStatusResponse.FromString, ) + self.Push = channel.unary_unary( + '/v1.Agent/Push', + request_serializer=pennsieve_dot_protos_dot_agent__pb2.PushRequest.SerializeToString, + response_deserializer=pennsieve_dot_protos_dot_agent__pb2.SimpleStatusResponse.FromString, + ) self.GetMapDiff = channel.unary_unary( '/v1.Agent/GetMapDiff', request_serializer=pennsieve_dot_protos_dot_agent__pb2.MapDiffRequest.SerializeToString, @@ -149,6 +154,11 @@ def __init__(self, channel): request_serializer=pennsieve_dot_protos_dot_agent__pb2.RegisterRequest.SerializeToString, response_deserializer=pennsieve_dot_protos_dot_agent__pb2.RegisterResponse.FromString, ) + self.Deregister = channel.unary_unary( + '/v1.Agent/Deregister', + request_serializer=pennsieve_dot_protos_dot_agent__pb2.DeregisterRequest.SerializeToString, + response_deserializer=pennsieve_dot_protos_dot_agent__pb2.DeregisterResponse.FromString, + ) self.GetTimeseriesChannels = channel.unary_unary( '/v1.Agent/GetTimeseriesChannels', request_serializer=pennsieve_dot_protos_dot_agent__pb2.GetTimeseriesChannelsRequest.SerializeToString, @@ -262,6 +272,12 @@ def Pull(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def Push(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def GetMapDiff(self, request, context): """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) @@ -339,6 +355,12 @@ def Register(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def Deregister(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def GetTimeseriesChannels(self, request, context): """Timeseries Endpoints """ @@ -436,6 +458,11 @@ def add_AgentServicer_to_server(servicer, server): request_deserializer=pennsieve_dot_protos_dot_agent__pb2.PullRequest.FromString, response_serializer=pennsieve_dot_protos_dot_agent__pb2.SimpleStatusResponse.SerializeToString, ), + 'Push': grpc.unary_unary_rpc_method_handler( + servicer.Push, + request_deserializer=pennsieve_dot_protos_dot_agent__pb2.PushRequest.FromString, + response_serializer=pennsieve_dot_protos_dot_agent__pb2.SimpleStatusResponse.SerializeToString, + ), 'GetMapDiff': grpc.unary_unary_rpc_method_handler( servicer.GetMapDiff, request_deserializer=pennsieve_dot_protos_dot_agent__pb2.MapDiffRequest.FromString, @@ -496,6 +523,11 @@ def add_AgentServicer_to_server(servicer, server): request_deserializer=pennsieve_dot_protos_dot_agent__pb2.RegisterRequest.FromString, response_serializer=pennsieve_dot_protos_dot_agent__pb2.RegisterResponse.SerializeToString, ), + 'Deregister': grpc.unary_unary_rpc_method_handler( + servicer.Deregister, + request_deserializer=pennsieve_dot_protos_dot_agent__pb2.DeregisterRequest.FromString, + response_serializer=pennsieve_dot_protos_dot_agent__pb2.DeregisterResponse.SerializeToString, + ), 'GetTimeseriesChannels': grpc.unary_unary_rpc_method_handler( servicer.GetTimeseriesChannels, request_deserializer=pennsieve_dot_protos_dot_agent__pb2.GetTimeseriesChannelsRequest.FromString, @@ -776,6 +808,23 @@ def Pull(request, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod + def Push(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/v1.Agent/Push', + pennsieve_dot_protos_dot_agent__pb2.PushRequest.SerializeToString, + pennsieve_dot_protos_dot_agent__pb2.SimpleStatusResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod def GetMapDiff(request, target, @@ -980,6 +1029,23 @@ def Register(request, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod + def Deregister(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/v1.Agent/Deregister', + pennsieve_dot_protos_dot_agent__pb2.DeregisterRequest.SerializeToString, + pennsieve_dot_protos_dot_agent__pb2.DeregisterResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod def GetTimeseriesChannels(request, target, From 417ea9779fffd76b9e2be52967f6afd8040bf976 Mon Sep 17 00:00:00 2001 From: "ddefreitas.exe" <1959720+darrell-d@users.noreply.github.com> Date: Tue, 21 Apr 2026 17:02:31 -0400 Subject: [PATCH 2/5] add Map wrapper for pennsieve map / pull / push / diff New Map class mirrors the manifest and timeSeries wrappers: constructed against the agent stub, exposes the four map RPCs, and adds wait helpers for the two fire-and-forget flows: - wait_for_pull polls .pennsieve/state.json for isLocal=True entries, since the agent doesn't emit pull-progress events. - wait_for_push subscribes and counts upload_status COMPLETE messages, which the existing UploadManifest flow already emits. Wired onto Pennsieve.connect() as client.map. Tests cover RPC dispatch, both pull wait happy path / timeout / late-arrival, invalid state.json, and push completion counting / timeout via a fake streaming stub. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/pennsieve/map.py | 222 +++++++++++++++++++++++++++++++++++++ src/pennsieve/pennsieve.py | 3 + tests/test_map.py | 191 +++++++++++++++++++++++++++++++ 3 files changed, 416 insertions(+) create mode 100644 src/pennsieve/map.py create mode 100644 tests/test_map.py diff --git a/src/pennsieve/map.py b/src/pennsieve/map.py new file mode 100644 index 0000000..6886e40 --- /dev/null +++ b/src/pennsieve/map.py @@ -0,0 +1,222 @@ +""" +Pennsieve Map feature — client-side wrapper. + +Mirrors the `pennsieve map` / `map pull` / `map push` / `map diff` CLI +commands that live in the Go agent. The gRPC calls return as soon as the +agent has started the work; long-running operations (pull, push) execute +in goroutines on the agent side. The `wait_for_*` helpers here let callers +block until completion when needed. +""" + +from __future__ import annotations + +import json +import os +import threading +import time +from pathlib import Path +from typing import Iterable, Optional + +from .protos import agent_pb2 + + +class Map: + """Operations on a Pennsieve Mapped Dataset. + + A mapped dataset is a local folder that mirrors a Pennsieve dataset's + tree as empty placeholder files, with a hidden `.pennsieve/` directory + holding the workspace manifest and pull state. Users pull selected + subfolders to get real bytes, and push to upload new files back. + + Methods: + -------- + map(dataset_id, target_folder): + Create a new mapped dataset at target_folder. + pull(path): + Download real content for files under `path` in a mapped dataset. + push(path): + Upload any new local files under `path` back to the mapped dataset. + diff(path): + Return added / changed / renamed / moved / deleted file status. + wait_for_pull(target_folder, timeout=...): + Block until pulled files appear in state.json. + wait_for_push(expected_files, subscriber_id, timeout=...): + Block until upload_status COMPLETE events match expected_files. + """ + + def __init__(self, stub): + self._stub = stub + + # ---------- RPCs ---------- + + def map(self, dataset_id: str, target_folder: str): + """Create a new mapped dataset on disk. + + Returns a SimpleStatusResponse. The agent downloads the workspace + manifest and creates placeholder files for every entry. + """ + request = agent_pb2.MapRequest( + dataset_id=dataset_id, + target_folder=str(target_folder), + ) + return self._stub.Map(request=request) + + def pull(self, path: str): + """Pull real file bytes for files under `path`. + + `path` can be any file or folder inside a mapped dataset; the agent + walks up to find the dataset root. Returns a SimpleStatusResponse + once the pull has been kicked off — work continues in the background. + Use `wait_for_pull` to block until it finishes. + """ + request = agent_pb2.PullRequest(path=str(path)) + return self._stub.Pull(request=request) + + def push(self, path: str): + """Push new local files under `path` back to the mapped dataset. + + Only ADDED files are uploaded (CHANGED / RENAMED / MOVED / DELETED + are ignored by the agent today). Returns immediately; use + `wait_for_push` with the expected file count to block. + """ + request = agent_pb2.PushRequest(path=str(path)) + return self._stub.Push(request=request) + + def diff(self, path: str): + """Return local vs. remote diff for the mapped dataset at `path`.""" + request = agent_pb2.MapDiffRequest(path=str(path)) + return self._stub.GetMapDiff(request=request) + + # ---------- wait helpers ---------- + + def wait_for_pull( + self, + target_folder: str, + expected_relative_paths: Optional[Iterable[str]] = None, + timeout: float = 300.0, + poll_interval: float = 0.5, + ) -> None: + """Block until expected files are pulled. + + Polls `/.pennsieve/state.json`. A file counts as + pulled when it has an entry in the state file with `isLocal=true`. + + Pull only records files that were actually requested, so when + `expected_relative_paths` is None we wait for any non-zero set of + local files to appear — which is only useful when the caller knows + pull has been issued against an empty prior state. Prefer passing + the set of paths you asked to pull. + + Paths are matched against the `path` field of state.json records, + which the agent writes with forward slashes relative to the + dataset root. + + Raises TimeoutError if the deadline elapses. + """ + state_path = Path(target_folder) / ".pennsieve" / "state.json" + expected: Optional[set[str]] = None + if expected_relative_paths is not None: + expected = {p.replace("\\", "/").lstrip("/") for p in expected_relative_paths} + + deadline = time.monotonic() + timeout + while True: + local_paths = _read_local_state_paths(state_path) + + if expected is None: + if local_paths: + return + else: + if expected.issubset(local_paths): + return + + if time.monotonic() >= deadline: + missing = expected - local_paths if expected is not None else set() + raise TimeoutError( + f"wait_for_pull timed out after {timeout}s; " + f"missing {len(missing)} file(s): {sorted(missing)[:5]}" + ) + time.sleep(poll_interval) + + def wait_for_push( + self, + expected_files: int, + subscriber_id: int, + timeout: float = 600.0, + ) -> int: + """Block until `expected_files` upload-status COMPLETE events arrive. + + Opens a Subscribe stream against the agent and counts + SubscribeResponse messages whose `upload_status.status` is COMPLETE + (enum value 2). Returns the number of COMPLETE events observed + (should equal `expected_files` on success). + + `subscriber_id` must be unique per subscriber within the agent's + lifetime. Picking os.getpid() + a counter works for most cases. + + Raises TimeoutError if the deadline elapses before enough events + arrive. The subscribe stream is closed either way. + """ + completed = 0 + done = threading.Event() + error: list[BaseException] = [] + + def consume(): + nonlocal completed + try: + request = agent_pb2.SubscribeRequest(id=subscriber_id) + for response in self._stub.Subscribe(request=request): + # type==1 is UPLOAD_STATUS in the SubscribeResponse enum + if response.type == 1 and response.upload_status.status == 2: + completed += 1 + if completed >= expected_files: + done.set() + return + except BaseException as exc: # includes grpc.RpcError on cancel + error.append(exc) + done.set() + + t = threading.Thread(target=consume, daemon=True) + t.start() + + finished = done.wait(timeout=timeout) + # Stop the subscriber so the stream closes promptly. + try: + self._stub.Unsubscribe( + request=agent_pb2.SubscribeRequest(id=subscriber_id), + ) + except Exception: + pass + + if not finished: + raise TimeoutError( + f"wait_for_push timed out after {timeout}s; " + f"observed {completed}/{expected_files} COMPLETE event(s)" + ) + if error and completed < expected_files: + # Surface the stream error only if we didn't get enough events + # first; otherwise the error is just the stream shutdown and + # is expected. + raise error[0] + return completed + + +def _read_local_state_paths(state_path: Path) -> set[str]: + """Return the set of relative paths in state.json with isLocal=True. + + Returns an empty set if the file doesn't exist or isn't yet valid JSON + (the agent writes the file after pulling every batch; a partial write + is rare but possible, so we treat parse errors as "not ready"). + """ + if not state_path.exists(): + return set() + try: + with state_path.open("r") as fh: + data = json.load(fh) + except (OSError, json.JSONDecodeError): + return set() + + out: set[str] = set() + for record in data.get("files") or []: + if record.get("isLocal") and record.get("path"): + out.add(record["path"]) + return out diff --git a/src/pennsieve/pennsieve.py b/src/pennsieve/pennsieve.py index 49073af..7387b40 100644 --- a/src/pennsieve/pennsieve.py +++ b/src/pennsieve/pennsieve.py @@ -12,6 +12,7 @@ from .direct import API2_HOST_DEFAULT, API_HOST_DEFAULT from .direct.client import AbstractClient, BaseHttpApiClient, HttpApiClient from .manifest import Manifest +from .map import Map from .protos import agent_pb2, agent_pb2_grpc from .protos.agent_pb2_grpc import AgentStub from .session import APISession, APISessionProvider @@ -111,6 +112,7 @@ def __init__( self.dataset = None self.manifest = None self.timeseries = None + self.map = None if http_api_client is None: self.http_api = self.build_no_auth_http_api_client() else: @@ -167,6 +169,7 @@ def connect( self.manifest = Manifest(self.stub) self.timeseries = TimeSeries(self.stub) + self.map = Map(self.stub) print("Please set the dataset with use_dataset([name])") return self diff --git a/tests/test_map.py b/tests/test_map.py new file mode 100644 index 0000000..cdb0c2e --- /dev/null +++ b/tests/test_map.py @@ -0,0 +1,191 @@ +import json +import threading +import time +from pathlib import Path +from unittest.mock import MagicMock + +import pytest + +from pennsieve.map import Map, _read_local_state_paths +from pennsieve.protos import agent_pb2 + + +def test_map_rpc_wraps_request_with_dataset_id_and_target(): + stub = MagicMock() + m = Map(stub) + + m.map("N:dataset:abc", "/tmp/mapped") + + stub.Map.assert_called_once() + req = stub.Map.call_args.kwargs["request"] + assert isinstance(req, agent_pb2.MapRequest) + assert req.dataset_id == "N:dataset:abc" + assert req.target_folder == "/tmp/mapped" + + +def test_pull_push_diff_forward_to_stub(): + stub = MagicMock() + m = Map(stub) + + m.pull("/tmp/mapped/folder") + assert isinstance(stub.Pull.call_args.kwargs["request"], agent_pb2.PullRequest) + assert stub.Pull.call_args.kwargs["request"].path == "/tmp/mapped/folder" + + m.push("/tmp/mapped") + assert isinstance(stub.Push.call_args.kwargs["request"], agent_pb2.PushRequest) + assert stub.Push.call_args.kwargs["request"].path == "/tmp/mapped" + + m.diff("/tmp/mapped") + assert isinstance(stub.GetMapDiff.call_args.kwargs["request"], agent_pb2.MapDiffRequest) + assert stub.GetMapDiff.call_args.kwargs["request"].path == "/tmp/mapped" + + +def _write_state(target: Path, records): + pennsieve_dir = target / ".pennsieve" + pennsieve_dir.mkdir(parents=True, exist_ok=True) + (pennsieve_dir / "state.json").write_text( + json.dumps( + { + "lastFetch": "2026-04-20T00:00:00Z", + "lastPull": "2026-04-20T00:00:00Z", + "files": records, + } + ) + ) + + +def test_wait_for_pull_returns_when_expected_paths_local(tmp_path): + m = Map(MagicMock()) + + _write_state( + tmp_path, + [ + {"path": "folder/a.lay", "isLocal": True, "pullTime": "2026-04-20T00:00:00Z"}, + {"path": "folder/b.lay", "isLocal": True, "pullTime": "2026-04-20T00:00:00Z"}, + ], + ) + + m.wait_for_pull( + target_folder=str(tmp_path), + expected_relative_paths=["folder/a.lay", "folder/b.lay"], + timeout=1.0, + poll_interval=0.01, + ) # must not raise + + +def test_wait_for_pull_times_out_when_paths_missing(tmp_path): + m = Map(MagicMock()) + _write_state(tmp_path, [{"path": "folder/a.lay", "isLocal": True}]) + + with pytest.raises(TimeoutError) as exc: + m.wait_for_pull( + target_folder=str(tmp_path), + expected_relative_paths=["folder/a.lay", "folder/missing.lay"], + timeout=0.2, + poll_interval=0.05, + ) + assert "folder/missing.lay" in str(exc.value) + + +def test_wait_for_pull_ignores_non_local_records(tmp_path): + m = Map(MagicMock()) + _write_state( + tmp_path, + [ + {"path": "folder/a.lay", "isLocal": False}, + {"path": "folder/a.lay", "isLocal": True}, + ], + ) + # Latest-wins isn't defined; presence of any isLocal=True record is enough. + m.wait_for_pull( + target_folder=str(tmp_path), + expected_relative_paths=["folder/a.lay"], + timeout=0.5, + poll_interval=0.01, + ) + + +def test_wait_for_pull_polls_until_state_appears(tmp_path): + m = Map(MagicMock()) + + def write_later(): + time.sleep(0.05) + _write_state( + tmp_path, + [{"path": "folder/a.lay", "isLocal": True}], + ) + + t = threading.Thread(target=write_later) + t.start() + try: + m.wait_for_pull( + target_folder=str(tmp_path), + expected_relative_paths=["folder/a.lay"], + timeout=1.0, + poll_interval=0.01, + ) + finally: + t.join() + + +def test_read_local_state_paths_returns_empty_when_missing(tmp_path): + assert _read_local_state_paths(tmp_path / "nope.json") == set() + + +def test_read_local_state_paths_tolerates_invalid_json(tmp_path): + p = tmp_path / "state.json" + p.write_text("{not valid") + assert _read_local_state_paths(p) == set() + + +class _FakeSubscribeResponse: + """Minimal duck-type for SubscribeResponse used by wait_for_push.""" + + class _UploadStatus: + def __init__(self, status): + self.status = status + + def __init__(self, type_, upload_status_code=None): + self.type = type_ + self.upload_status = self._UploadStatus(upload_status_code or 0) + + +def test_wait_for_push_counts_complete_events(): + events = [ + _FakeSubscribeResponse(type_=0), # general info -- ignored + _FakeSubscribeResponse(type_=1, upload_status_code=1), # IN_PROGRESS + _FakeSubscribeResponse(type_=1, upload_status_code=2), # COMPLETE #1 + _FakeSubscribeResponse(type_=1, upload_status_code=2), # COMPLETE #2 + ] + + stub = MagicMock() + + def subscribe(request): + for e in events: + yield e + # Then block so the thread doesn't exit immediately after yielding + # (simulating a live stream). + while True: + time.sleep(0.05) + + stub.Subscribe.side_effect = lambda request: subscribe(request) + + m = Map(stub) + count = m.wait_for_push(expected_files=2, subscriber_id=9001, timeout=2.0) + assert count == 2 + stub.Unsubscribe.assert_called_once() + + +def test_wait_for_push_times_out_when_not_enough_events(): + stub = MagicMock() + + def subscribe(request): + yield _FakeSubscribeResponse(type_=1, upload_status_code=2) # one COMPLETE + while True: + time.sleep(0.05) + + stub.Subscribe.side_effect = lambda request: subscribe(request) + + m = Map(stub) + with pytest.raises(TimeoutError): + m.wait_for_push(expected_files=2, subscriber_id=9002, timeout=0.3) From 424597f6326030ff11ede5a558c9587dba1c23e7 Mon Sep 17 00:00:00 2001 From: "ddefreitas.exe" <1959720+darrell-d@users.noreply.github.com> Date: Thu, 23 Apr 2026 14:38:47 -0400 Subject: [PATCH 3/5] formatting clean up and ignore protos folder for formatting --- pyproject.toml | 6 ++++++ src/pennsieve/pennsieve.py | 13 ++++++++----- tests/test_map.py | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 419f991..eeb433d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,9 +69,15 @@ exclude = ''' | build | dist | docs + | src/pennsieve/protos )/ ''' +[tool.isort] +profile = "black" +line_length = 99 +skip_glob = ["src/pennsieve/protos/*"] + [build-system] requires = [ diff --git a/src/pennsieve/pennsieve.py b/src/pennsieve/pennsieve.py index 7387b40..5c5ccb7 100644 --- a/src/pennsieve/pennsieve.py +++ b/src/pennsieve/pennsieve.py @@ -1,6 +1,7 @@ """ Copyright (c) 2022 Patryk Orzechowski | Wagenaar Lab | University of Pennsylvania """ + from __future__ import annotations import logging @@ -214,11 +215,13 @@ def get_datasets(self): if isinstance(response, list) and len(response) > 0: self._datasets = dict( map( - lambda x: (x["content"]["name"], x["content"]["id"]) - if "content" in x.keys() - and "name" in x["content"].keys() - and "id" in x["content"].keys() - else None, + lambda x: ( + (x["content"]["name"], x["content"]["id"]) + if "content" in x.keys() + and "name" in x["content"].keys() + and "id" in x["content"].keys() + else None + ), response, ) ) diff --git a/tests/test_map.py b/tests/test_map.py index cdb0c2e..79c726a 100644 --- a/tests/test_map.py +++ b/tests/test_map.py @@ -152,7 +152,7 @@ def __init__(self, type_, upload_status_code=None): def test_wait_for_push_counts_complete_events(): events = [ - _FakeSubscribeResponse(type_=0), # general info -- ignored + _FakeSubscribeResponse(type_=0), # general info -- ignored _FakeSubscribeResponse(type_=1, upload_status_code=1), # IN_PROGRESS _FakeSubscribeResponse(type_=1, upload_status_code=2), # COMPLETE #1 _FakeSubscribeResponse(type_=1, upload_status_code=2), # COMPLETE #2 From a600bcbfadf42731e83bd79de288bfa70a9e8b29 Mon Sep 17 00:00:00 2001 From: "ddefreitas.exe" <1959720+darrell-d@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:01:14 -0400 Subject: [PATCH 4/5] switch map wait helpers to idle-timeout semantics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces blanket timeouts on wait_for_pull / wait_for_push with an idle-timeout that resets on each progress event, so transfers of any total duration succeed as long as the agent keeps making progress. Fails fast only when the stream actually goes silent. Defaults chosen for Pennsieve's dataset scale (~300-400 GB, ~700 MB max file): - wait_for_pull: 1800s (30 min) — must cover worst-case single-file download since state.json only updates per file completion. - wait_for_push: 300s (5 min) — the agent emits IN_PROGRESS on every S3 chunk read, so any real silence means a stall. Adds a Mapped Datasets section to the README documenting the wrappers, the two progress signals, and how to override idle_timeout. Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 42 ++++++++++++++++++++++++++++ src/pennsieve/map.py | 66 +++++++++++++++++++++++++++++++------------- tests/test_map.py | 12 ++++---- 3 files changed, 95 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 18d3dee..9701cdb 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,48 @@ To create a package and upload it to PyPI, first update the package version in t twine upload dist/* ``` +Mapped Datasets +--------------- + +The `client.map` wrapper exposes the agent's mapped-dataset RPCs (`map`, +`pull`, `push`, `diff`) as a small Python API. The four RPCs return as soon +as the agent has accepted the work — `pull` and `push` then run in the +background inside the agent — so `client.map` also ships two blocking +helpers: `wait_for_pull` and `wait_for_push`. + +```python +client.map.map(dataset_id="N:dataset:...", target_folder="/data/foo") +client.map.pull("/data/foo/subfolder") +client.map.wait_for_pull("/data/foo", expected_relative_paths=[...]) + +client.map.push("/data/foo") +client.map.wait_for_push(expected_files=N, subscriber_id=os.getpid()) +``` + +### Timeouts + +Both wait helpers use an **idle timeout** rather than a total-duration +timeout — the deadline resets each time progress is observed, so a +multi-hour single-file transfer is fine as long as the agent keeps making +progress. You only hit a `TimeoutError` when the agent goes silent. + +**`wait_for_pull`** — default `idle_timeout=1800` (30 min) +- *Progress signal:* a new file entry appears in `.pennsieve/state.json`, which the agent writes on each file's completion. +- *Why 30 min:* the window has to cover the worst-case single-file download end-to-end, since there is no per-chunk progress for pulls. + +**`wait_for_push`** — default `idle_timeout=300` (5 min) +- *Progress signal:* any `UPLOAD_STATUS` event (`INIT` / `IN_PROGRESS` / `COMPLETE`). The agent emits `IN_PROGRESS` on every S3 chunk read, so events stream continuously during healthy uploads. +- *Why 5 min:* events are frequent during healthy uploads, so 5 minutes of silence indicates a real stall (network hang, agent wedge) rather than slow progress. + +Override either default by passing `idle_timeout=` when you know +your transfer characteristics — e.g. pulls over a very slow link with large +individual files, or tighter CI smoke-tests where you want to fail faster. + +```python +client.map.wait_for_pull(target_folder, idle_timeout=3600) # 1 hour +client.map.wait_for_push(expected_files=N, subscriber_id=..., idle_timeout=60) # 1 minute +``` + Documentation ------------- diff --git a/src/pennsieve/map.py b/src/pennsieve/map.py index 6886e40..e866bac 100644 --- a/src/pennsieve/map.py +++ b/src/pennsieve/map.py @@ -38,10 +38,12 @@ class Map: Upload any new local files under `path` back to the mapped dataset. diff(path): Return added / changed / renamed / moved / deleted file status. - wait_for_pull(target_folder, timeout=...): - Block until pulled files appear in state.json. - wait_for_push(expected_files, subscriber_id, timeout=...): - Block until upload_status COMPLETE events match expected_files. + wait_for_pull(target_folder, idle_timeout=...): + Block until pulled files appear in state.json. Fails only if no new + files appear within `idle_timeout` seconds — total duration unbounded. + wait_for_push(expected_files, subscriber_id, idle_timeout=...): + Block until upload_status COMPLETE events match expected_files. Fails + only if no upload-status event arrives within `idle_timeout` seconds. """ def __init__(self, stub): @@ -93,7 +95,7 @@ def wait_for_pull( self, target_folder: str, expected_relative_paths: Optional[Iterable[str]] = None, - timeout: float = 300.0, + idle_timeout: float = 1800.0, poll_interval: float = 0.5, ) -> None: """Block until expected files are pulled. @@ -111,14 +113,19 @@ def wait_for_pull( which the agent writes with forward slashes relative to the dataset root. - Raises TimeoutError if the deadline elapses. + `idle_timeout` is the max seconds allowed between progress events + (a new file appearing in state.json). The deadline resets each time + the local-files set grows, so total duration is unbounded — fits + TB/PB-scale pulls where a single file can take hours. Raises + TimeoutError only if no new file appears within `idle_timeout`. """ state_path = Path(target_folder) / ".pennsieve" / "state.json" expected: Optional[set[str]] = None if expected_relative_paths is not None: expected = {p.replace("\\", "/").lstrip("/") for p in expected_relative_paths} - deadline = time.monotonic() + timeout + last_progress = time.monotonic() + last_count = 0 while True: local_paths = _read_local_state_paths(state_path) @@ -129,10 +136,15 @@ def wait_for_pull( if expected.issubset(local_paths): return - if time.monotonic() >= deadline: + if len(local_paths) > last_count: + last_count = len(local_paths) + last_progress = time.monotonic() + + if time.monotonic() - last_progress >= idle_timeout: missing = expected - local_paths if expected is not None else set() raise TimeoutError( - f"wait_for_pull timed out after {timeout}s; " + f"wait_for_pull: no new files in {idle_timeout}s " + f"(have {last_count}); " f"missing {len(missing)} file(s): {sorted(missing)[:5]}" ) time.sleep(poll_interval) @@ -141,7 +153,7 @@ def wait_for_push( self, expected_files: int, subscriber_id: int, - timeout: float = 600.0, + idle_timeout: float = 300.0, ) -> int: """Block until `expected_files` upload-status COMPLETE events arrive. @@ -153,10 +165,15 @@ def wait_for_push( `subscriber_id` must be unique per subscriber within the agent's lifetime. Picking os.getpid() + a counter works for most cases. - Raises TimeoutError if the deadline elapses before enough events - arrive. The subscribe stream is closed either way. + `idle_timeout` is the max seconds allowed between upload-status + events (INIT / IN_PROGRESS / COMPLETE all count as progress). Each + event resets the idle window, so total duration is unbounded — a + multi-hour single-file upload is fine as long as the agent keeps + emitting progress. Raises TimeoutError only when the stream goes + silent for `idle_timeout` seconds. """ completed = 0 + progress = threading.Event() done = threading.Event() error: list[BaseException] = [] @@ -166,11 +183,13 @@ def consume(): request = agent_pb2.SubscribeRequest(id=subscriber_id) for response in self._stub.Subscribe(request=request): # type==1 is UPLOAD_STATUS in the SubscribeResponse enum - if response.type == 1 and response.upload_status.status == 2: - completed += 1 - if completed >= expected_files: - done.set() - return + if response.type == 1: + progress.set() + if response.upload_status.status == 2: + completed += 1 + if completed >= expected_files: + done.set() + return except BaseException as exc: # includes grpc.RpcError on cancel error.append(exc) done.set() @@ -178,7 +197,16 @@ def consume(): t = threading.Thread(target=consume, daemon=True) t.start() - finished = done.wait(timeout=timeout) + finished = False + while not finished: + progress.clear() + if done.wait(timeout=idle_timeout): + finished = True + break + if not progress.is_set(): + # No upload-status event arrived during the whole window. + break + # Stop the subscriber so the stream closes promptly. try: self._stub.Unsubscribe( @@ -189,7 +217,7 @@ def consume(): if not finished: raise TimeoutError( - f"wait_for_push timed out after {timeout}s; " + f"wait_for_push: no upload-status event in {idle_timeout}s; " f"observed {completed}/{expected_files} COMPLETE event(s)" ) if error and completed < expected_files: diff --git a/tests/test_map.py b/tests/test_map.py index 79c726a..edbabc5 100644 --- a/tests/test_map.py +++ b/tests/test_map.py @@ -68,7 +68,7 @@ def test_wait_for_pull_returns_when_expected_paths_local(tmp_path): m.wait_for_pull( target_folder=str(tmp_path), expected_relative_paths=["folder/a.lay", "folder/b.lay"], - timeout=1.0, + idle_timeout=1.0, poll_interval=0.01, ) # must not raise @@ -81,7 +81,7 @@ def test_wait_for_pull_times_out_when_paths_missing(tmp_path): m.wait_for_pull( target_folder=str(tmp_path), expected_relative_paths=["folder/a.lay", "folder/missing.lay"], - timeout=0.2, + idle_timeout=0.2, poll_interval=0.05, ) assert "folder/missing.lay" in str(exc.value) @@ -100,7 +100,7 @@ def test_wait_for_pull_ignores_non_local_records(tmp_path): m.wait_for_pull( target_folder=str(tmp_path), expected_relative_paths=["folder/a.lay"], - timeout=0.5, + idle_timeout=0.5, poll_interval=0.01, ) @@ -121,7 +121,7 @@ def write_later(): m.wait_for_pull( target_folder=str(tmp_path), expected_relative_paths=["folder/a.lay"], - timeout=1.0, + idle_timeout=1.0, poll_interval=0.01, ) finally: @@ -171,7 +171,7 @@ def subscribe(request): stub.Subscribe.side_effect = lambda request: subscribe(request) m = Map(stub) - count = m.wait_for_push(expected_files=2, subscriber_id=9001, timeout=2.0) + count = m.wait_for_push(expected_files=2, subscriber_id=9001, idle_timeout=2.0) assert count == 2 stub.Unsubscribe.assert_called_once() @@ -188,4 +188,4 @@ def subscribe(request): m = Map(stub) with pytest.raises(TimeoutError): - m.wait_for_push(expected_files=2, subscriber_id=9002, timeout=0.3) + m.wait_for_push(expected_files=2, subscriber_id=9002, idle_timeout=0.3) From 842f48f35be6497295b17a7498955709d1828405 Mon Sep 17 00:00:00 2001 From: "ddefreitas.exe" <1959720+darrell-d@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:14:06 -0400 Subject: [PATCH 5/5] use absolute paths --- src/pennsieve/map.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/pennsieve/map.py b/src/pennsieve/map.py index e866bac..20add13 100644 --- a/src/pennsieve/map.py +++ b/src/pennsieve/map.py @@ -59,7 +59,7 @@ def map(self, dataset_id: str, target_folder: str): """ request = agent_pb2.MapRequest( dataset_id=dataset_id, - target_folder=str(target_folder), + target_folder=_abspath(target_folder), ) return self._stub.Map(request=request) @@ -71,7 +71,7 @@ def pull(self, path: str): once the pull has been kicked off — work continues in the background. Use `wait_for_pull` to block until it finishes. """ - request = agent_pb2.PullRequest(path=str(path)) + request = agent_pb2.PullRequest(path=_abspath(path)) return self._stub.Pull(request=request) def push(self, path: str): @@ -81,12 +81,12 @@ def push(self, path: str): are ignored by the agent today). Returns immediately; use `wait_for_push` with the expected file count to block. """ - request = agent_pb2.PushRequest(path=str(path)) + request = agent_pb2.PushRequest(path=_abspath(path)) return self._stub.Push(request=request) def diff(self, path: str): """Return local vs. remote diff for the mapped dataset at `path`.""" - request = agent_pb2.MapDiffRequest(path=str(path)) + request = agent_pb2.MapDiffRequest(path=_abspath(path)) return self._stub.GetMapDiff(request=request) # ---------- wait helpers ---------- @@ -228,6 +228,10 @@ def consume(): return completed +def _abspath(path: str) -> str: + return os.path.abspath(os.path.expanduser(str(path))) + + def _read_local_state_paths(state_path: Path) -> set[str]: """Return the set of relative paths in state.json with isLocal=True.