Package: scope-py
ScopeScope is a Python library inspired byopticsfrom functional programming. The aim of Scope is to make various flavors ofopticsnatural tools for Python programmers without requiring knowledge of the underlying math. Put simply,opticsprovide an abstraction for focusing on ("getting") and manipulating ("setting") data within larger and potentially nested structures.This library favors usability over rigor and makes some decisions which increase utility at the expense of overloading and extending established terminology. For example,traversalsin the standard usage, provide a means of focusing on multiple parts of a datastructure but do not provide similar setting behavior, whereas instances of thescope.Traversalclass do provide a way to set multiple parts of a larger datastructure.InstallInstall by runningpip install scope-pyor by cloning this repo and runningpip install .in the project root directory.IntroductionThe Scope library targets manipulation of JSON-like nested structures, which in Python are built from dictionaries, and lists, but customopticsare definable. Scope has a few classes you should be aware of;Lens: Base class providing get and put methods. Can be composed with other lenses.ParallelLens: Allows multiple lenses to be used in parallel.Traversal: Provides functionality for working with sequences of data.ItemLens: A lens focused on a specific item in an object which implements the__getitem__dunder method.CRUDLens: An extension of a Lens that includes create and delete methods.ParallelCRUDLens: Allows multiple CRUD lenses to be used in parallel.CRUDTraversal: Extension of the CRUDLens for working with sequences of data.Importantly, aLensfocuses on one thing and aTraversalsfocuses on many things. ACRUDLensextends the get/put functionality of lenses with additional create/delete functionality.UsageBasic lens composition:importscope# create a lens that focuses on item 'b' after item 'a'lens=scope.id['a']['b']# lens = scope.compose_lenses(scope.id['a'], scope.id['b']) <-- alt. syntaxdata={'a':{'b':3}}# note -- lens(data) is an alias for lens.get(data)assertlens(data)==3assertlens.put(4)(data)=={'a':{'b':4}}CRUDTraversal usage:lens=CRUDTraversal(ItemCRUDLens('a'),ItemCRUDLens('c'))# lens = ItemCRUDLens('a')[::]['c'] <-- alt. syntaxdata={'a':[{'b':1},{'b':3}]}# "{'a': [{'b': 1, 'c': 2}, {'b': 3, 'c': 4}]}"print(lens.create([2,4])(data))Create a custom attribute lens:# create a lens that gets/sets the attribute "my_attr" on an objectmy_attr_lens=scope.Lens(lambdadata:getattr(data,'my_attr'),lambdavalue:lambdadata:setattr(data,'my_attr',value))Parallel lens usage:x_lens,y_lens=scope.id['x'],scope.id['y']# create a lens which focuses on 'x' and 'y' in parallelparallel_lens=x_lens|y_lens# parallel_lens = scope.ParallelLens(x_lens, y_lens) <-- alt. syntaxdata={'x':2,'y':3}assertsum(parallel_lens(data))==5Todo‘s[] Clean up unused files leftover from cloned template repo[] Tests to achieve 100% code coverage[] Add afiltermethod to all classes which accepts a predicate function and applies it to the focus[] Add tests passing and code coverage badges using Github PagesLicenseThis project is open-sourced under the MIT license. SeeLICENSEfor more information.ContactFor questions or issues, please open an issue on GitHub.