{"id":22433928,"url":"https://github.com/jericho/picton","last_synced_at":"2025-08-01T13:31:06.459Z","repository":{"id":48126534,"uuid":"64042714","full_name":"Jericho/Picton","owner":"Jericho","description":"The Picton project is a convenient library for working with Microsoft Azure. Among other things, it contains extension methods and abstrations for StorageAccount, BlobClient, QueueClient, etc.","archived":false,"fork":false,"pushed_at":"2024-11-03T14:00:22.000Z","size":541,"stargazers_count":3,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"develop","last_synced_at":"2024-12-05T04:19:16.069Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Jericho.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-07-24T01:10:39.000Z","updated_at":"2024-11-03T14:00:26.000Z","dependencies_parsed_at":"2023-12-17T20:38:01.834Z","dependency_job_id":"4f092386-034d-4621-8788-11041e7ee856","html_url":"https://github.com/Jericho/Picton","commit_stats":null,"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jericho%2FPicton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jericho%2FPicton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jericho%2FPicton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jericho%2FPicton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jericho","download_url":"https://codeload.github.com/Jericho/Picton/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228377525,"owners_count":17910449,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-05T22:16:56.348Z","updated_at":"2024-12-05T22:16:57.075Z","avatar_url":"https://github.com/Jericho.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Picton\n\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://jericho.mit-license.org/)\n[![Build status](https://ci.appveyor.com/api/projects/status/9guqjro396ytudv3?svg=true)](https://ci.appveyor.com/project/Jericho/picton)\n[![Coverage Status](https://coveralls.io/repos/github/Jericho/Picton/badge.svg?branch=master)](https://coveralls.io/github/Jericho/Picton?branch=master)\n[![CodeFactor](https://www.codefactor.io/repository/github/jericho/picton/badge)](https://www.codefactor.io/repository/github/jericho/picton)\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2FJericho%2FPicton.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2FJericho%2FPicton?ref=badge_shield)\n\n## About\n\nPicton is a library intendent to make it easier to work with Azure storage. \n\nThe main features in this library are:\n\n#### 1) Extension metods:\nThe extension methods allow operations on blob while holding a lock (also known as a 'lease'). Specifically:\n\n- Lock a blob for a given period of time with retries in case it is already locked by another process\n- Extend an existing lease\n- Release an existing lease\n- Overwrite the content of a blob with a given string (there are also similar methods to upload a byte array or a stream)\n- Append a given string to a blob (there are also similar methods to append a byte array or a stream)\n- Update the metadata associated with a blob\n- Download the content of a blob to a `string` (there is also a similar method to download the content to a `byte[]`)\n- Make a copy of a blob\n- Get a URI which can be used to gain access to a blob for a limid period of time\n\n\n#### 2) Abstractions:\nEarly versions of the Picton library contained several interfaces to overcome the fact that most classed in the Azure Storage library where sealed and/or their methods where not marked as virtual and therefore not \"mockable\".\nIn [release 7.0 of the Azure Storage library](https://github.com/Azure/azure-storage-net/releases/tag/v7.0.0), Microsoft unsealed most classes and marked most methods as virtual which is quite significant because it allows mocking these classes when they are injected in one of your own classes. \nThe Azure Storage library was further improved in [version 8.0](https://github.com/Azure/azure-storage-net/releases/tag/v8.0.0) to update the `Get*Reference` methods with the \"virtual\" qualifier.\nThe Azure Storage library was again improved in [version 9.0](https://github.com/Azure/azure-storage-net/releases/tag/v9.0.0) to unseal the `StorageAccount` class. This was the last hurdle that prevented \"mocking\" the Azure storage library in unit tests.\nThis means that all interfaces and wrapper classes in the Picton library have become obsolete and have ben removed in version 3.0.\n\n#### 3) Managers\nThe Blob and Queue managers are helpers that simplify common blob and queue related tasks. \nFor example, the QueueManager automatically serializes and stores a message to a temporary location if the message exceeds the maximum size allowed in an Azure queue.\nAnother example: the Blob queue can automatically request a lock (AKA lease) before attempting to modify the content of a blob and it automatically releases the lock once the operation is completed.\n\n#### 4) Misc\n- AzureEmulatorManager alows starting the Azure Storage Emulator which you may need prior to executing integration testing\n\n\n## Nuget\n\nPicton is available as a Nuget package.\n\n[![NuGet Version](https://img.shields.io/nuget/v/Picton.svg)](https://www.nuget.org/packages/Picton/)\n\n\n## Installation\n\nThe easiest way to include Picton in your C# project is by grabing the nuget package:\n\n```\nPM\u003e Install-Package Picton\n```\n\nOnce you have the Picton library properly referenced in your project, add the following namespace(s):\n\n```\nusing Picton;            // This is always required\nusing Picton.Managers;   // This is only required if you want to use BlobManager or QueueManager\n```\n\n## Usage\n\n\n#### 1) Blob extension metods:\nFist of all, some boilerplate code necessary for the code samples below:\n\n```\nvar cancellationToken = CancellationToken.None;\nvar connectionString = \"UseDevelopmentStorage=true\";\n\nvar container = new BlobContainerClient(connectionString, \"mycontainer\");\nawait container.CreateIfNotExistsAsync(PublicAccessType.None, cancellationToken).ConfigureAwait(false);\nvar blob = container.GetBlockBlobClient(\"MyBlob.txt\");\n```\n\nHere are a few examples how to use the extension methods:\n```\nvar leaseId = await blob.TryAcquireLeaseAsync(TimeSpan.FromSeconds(15), 5, cancellationToken).ConfigureAwait(false);\nawait blob.UploadTextAsync(\"Hello World\", leaseId, cancellationToken).ConfigureAwait(false);\nawait blob.AppendTextAsync(\"More content\", leaseId, cancellationToken).ConfigureAwait(false);\nawait blob.AppendTextAsync(\"Even more content\", leaseId, cancellationToken).ConfigureAwait(false);\nawait blob.TryRenewLeaseAsync(leaseId, cancellationToken).ConfigureAwait(false);\nawait blob.AppendTextAsync(\"More more more\", leaseId, cancellationToken).ConfigureAwait(false);\nawait blob.ReleaseLeaseAsync(leaseId, cancellationToken).ConfigureAwait(false);\n\nvar content = await blob.DownloadTextAsync(cancellationToken).ConfigureAwait(false);\nawait blob.CopyAsync(\"MyCopy.txt\", cancellationToken).ConfigureAwait(false);\n\nvar permission = SharedAccessBlobPermissions.Read;\nvar duration = TimeSpan.FromMinutes(30);\nvar accessUri = await blob.GetSharedAccessSignatureUri(permission, duration).ConfigureAwait(false);\n```\n\n\n#### 2) Managers\n\n```\nvar connectionString = \"UseDevelopmentStorage=true\";\nvar blobManager = new BlobManager(connectionString, \"mycontainer\");\n\nawait blobManager.CopyBlobAsync(\"test.txt\", \"test - Copy of.txt\", cancellationToken).ConfigureAwait(false);\n\nawait blobManager.UploadTextAsync(\"test2.txt\", \"Hello World\", cancellationToken: cancellationToken).ConfigureAwait(false);\nawait blobManager.AppendTextAsync(\"test2.txt\", \"qwerty\", cancellationToken: cancellationToken).ConfigureAwait(false);\n\nforeach (var blob in blobManager.ListBlobs(\"test\", false, false))\n{\n    Console.WriteLine(blob.Uri.AbsoluteUri);\n}\n\nawait blobManager.DeleteBlobAsync(\"test - Copy of.txt\", cancellationToken).ConfigureAwait(false);\nawait blobManager.DeleteBlobsWithPrefixAsync(\"test\", cancellationToken).ConfigureAwait(false);\n```\n\n#### 3) Misc\n\n```\nclass Program\n{\n    static void Main()\n    {\n        AzureEmulatorManager.EnsureStorageEmulatorIsStarted();\n\n        var cancellationToken = CancellationToken.None;\n        var connectionString = \"UseDevelopmentStorage=true\";\n        var container = new BlobContainerClient(connectionString, \"mycontainer\");\n\t\tawait container.CreateIfNotExistsAsync(PublicAccessType.None, cancellationToken).ConfigureAwait(false);\n    }\n}\n```\n\n\n## License\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2FJericho%2FPicton.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2FJericho%2FPicton?ref=badge_large)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjericho%2Fpicton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjericho%2Fpicton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjericho%2Fpicton/lists"}