{"id":23419419,"url":"https://github.com/bannsec/pycow","last_synced_at":"2025-04-12T12:44:40.143Z","repository":{"id":62579519,"uuid":"115968555","full_name":"bannsec/pyCoW","owner":"bannsec","description":"Attempt at creating Copy-On-Write library for Python","archived":false,"fork":false,"pushed_at":"2018-03-19T02:16:13.000Z","size":46,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-03-15T10:35:57.461Z","etag":null,"topics":["copy-on-write","cow","python"],"latest_commit_sha":null,"homepage":null,"language":"Python","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/bannsec.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}},"created_at":"2018-01-02T03:00:53.000Z","updated_at":"2023-09-28T10:47:06.000Z","dependencies_parsed_at":"2022-11-03T21:00:26.570Z","dependency_job_id":null,"html_url":"https://github.com/bannsec/pyCoW","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bannsec%2FpyCoW","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bannsec%2FpyCoW/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bannsec%2FpyCoW/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bannsec%2FpyCoW/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bannsec","download_url":"https://codeload.github.com/bannsec/pyCoW/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248570255,"owners_count":21126388,"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":["copy-on-write","cow","python"],"created_at":"2024-12-23T01:17:55.801Z","updated_at":"2025-04-12T12:44:40.121Z","avatar_url":"https://github.com/bannsec.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/bannsec/pyCoW.svg?branch=master)](https://travis-ci.org/bannsec/pyCoW)\n[![Coverage Status](https://coveralls.io/repos/github/bannsec/pyCoW/badge.svg?branch=master)](https://coveralls.io/github/bannsec/pyCoW?branch=master)\n\n# Overview\nThis is an attempt at implementing a generic Copy-on-Write base class for python.\n\n# How To Use\nFeel free to give it a shot. I doubt that it is bug-free, but it may be minimal enough bugs to be helpful to your project.\n\n## Setup\n\nThe basic way to integrate Copy-on-Write in the form of `pyCoW` into your project is to extend your classes with it. First step is to install pyCoW as you would a normal lib:\n\n```bash\n$ pip install pyCoW\n```\n\nNext, extend your class objects inheritance with it, as follows:\n\n```python\nfrom pyCoW import CoW\n\nclass MyClass(CoW):\n    pass\n```\n\nNote, if you already have class inheritance on your object, you need to be careful. `pyCoW` assumes that it will be the secondary class, so that any `super()` calls will resolve to the intended class. Thus, if your object extended `int`, the following would be the correct order:\n\n```python\nclass MyClass(int, CoW):\n    pass\n```\n\nAlso, note that it is important in the later case to override some magic methods with a simple stub. This allows `pyCoW` to manage those calls and work some copy-on-write magic in the middle. For instance, if you extended a dictionary, you would want `pyCoW` to handle managing your items. This could be done as follows:\n\n```python\nclass MyClass(dict, CoW):\n    def __setitem__(self, *args, **kwargs):\n        return CoW.__setitem__(self, *args, **kwargs)\n\n    def __getitem__(self, key):\n        return CoW.__getitem__(self, key)\n```\n\nWhat is happening there is that you are explicitly choosing to use `pyCoW`'s get and set item calls. `pyCoW` will do it's own checks and work under the covers, then call your primary handler which in this case is the dict object. The result is that it should be mostly transparent that you are using this.\n\n## Use\nThis library has a few main effects. First off, it attempts to be aggressive about not duplicating any of your items in memory. For instance, if you were to make two of the same attributes in different objects, you would only be making one actual object.\n\n```python\nfrom pyCoW import CoW\n\nclass MyClass(CoW):\n    pass\n\nobj = MyClass()\nobj2 = MyClass()\n\nobj.l = [1,2,3]\nobj2.l = [1,2,3]\n\nassert obj.l is obj2.l\n```\n\nIn this case i'm asserting not only that they are equal, but that they are the same object entirely. However, if i were to continue and update one of them, now i have two separate objects.\n\n```python\nobj.l.append(4)\nassert obj.l == [1,2,3,4]\nassert obj2.l == [1,2,3]\n```\n\nOne other key thing you can do on `CoW` objects is `copy`. In this case, you can think of `copy` as the python built-in `deepcopy` in that the object you get back should be a complete copy of the object in. The difference is that, since `CoW`'s version of `copy` utilizes aggressive caching and just-in-time copy, it will be substantially faster than `deepcopy` and will also take up much less memory on large objects. Example:\n\n```python\nfrom copy import copy\n\nobj = MyClass()\n# Do a bunch of things with obj\nobj2 = copy(obj)\n```\n\nIn this case, I'm using the `copy` method simply as a convenience wrapper to call `__copy__`. You could call that directly if you wished.\n\n# Gotchas\n## Variable Types\nVariable types have to be changed for this to work. The change is done automatically for you, and for the most part should be in the background. However, you will notice that the variable type you put in (such as `list`) comes back as a different type (such as `ProxyList`). The type should behave the same as you would expect, but if you use `type(x) == ` checks in your code, you will need to adjust for the proxy versions of those types.\n\n# Python Versions\nThis is being tested against 3.5+. There are known issues at the moment for 3.4, and anything below is untested.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbannsec%2Fpycow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbannsec%2Fpycow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbannsec%2Fpycow/lists"}