This is a package that allows you to create a key-value vault for storing variables in a global context

Overview

README

How to install?

pip3 install varvault

What is this?

This is a package that allows you to create a key-value vault for storing variables in a global context. It allows you to set up a keyring with pre-defined constants which act as keys for the vault. These constants are then what is stored inside the vault. A key is just a string, but the value that the key is mapped to can be assigned to any type of object in Python. If the object is serializable (like a list or a dict), it can also be writen to a JSON file
You can then use a decorator to annotate functions that you want to have use this vault to either store return variables in or to extract variables to be used as input for the function.

How does it work?

The way this works is that when you write a function, you annotate it with a special decorator (varvault.Vault.vaulter) that takes some arguments. This decorator will then handle any input arguments and return variables for you. The decorator takes some arguments that defines certain keys.

How about an example?

The best examples can be found in the test suites which can give a very good idea how it works and is guaranteed to be up-to-date.

import varvault


class Keyring(varvault.Keyring):
    arg1 = varvault.Key("arg1")
    arg2 = varvault.Key("arg2")


vault = varvault.create_vault(Keyring, "example-vault", "~/.vault/vault.json", varvault.VaultFlags.return_values_cannot_be_none()))


@vault.vaulter(return_keys=[Keyring.arg1, Keyring.arg2])
def create_args(arg1, arg2):
    return arg1, arg2


@vault.vaulter(input_keys=[Keyring.arg1, Keyring.arg2])
def use_args(**kwargs):
    arg1 = kwargs.get(Keyring.arg1)
    arg2 = kwargs.get(Keyring.arg2)

    print(f"{Keyring.arg1}: {arg1}, {Keyring.arg2}: {arg2}")


def run_create_args():
    create_args(1, 2)
    

def run_use_args():
    use_args()


if __name__ == "__main__":
    run_create_args()
    
    run_use_args()    
  1. In this example, we start by creating a class that defines a keyring. This keyring will be the keys used in the vault. Any key you use for storing variables or take variables out should be defined as a constant in this keyring (by default, this is the way to use it, but it is possible to be more flexible).

  2. Then we create the actual Vault-object. It's entirely possible to create a Vault without using the factory function, but the factory function will do some things for you to make it slightly easier. Creating the vault requires only two arguments and that is a class that inherits from the varvault.Keyring (a class based on the Keyring class here), and a name. Optionally, you can define some flags to further tweak the behavior of the vault. These tweaked behaviors include allowing for existing key-value pairs to be modified (this is not allowed by default), allowing return variables from functions defined with return keys to be None, and setting a flag to write some additional debug logs. You can also define a .JSON file to be used as a vault file to store all the arguments in.

  3. We create a function called create_args that takes some arguments (we have to insert variables into the vault somehow, right?) that we annotate with the vault decorator. We pass an argument to the decorator called return_keys. This argument tells the vault which keys this function will assign its return variables to. Note that the order of the return keys matter. In this case, the ingoing argument arg1 will be assigned to Keyring.arg1, and the ingoing argument arg2 will be assigned to Keyring.arg2. It's very possible to set return_var_key to a single string as well if you only have one variable to return. If you want more control over how return variables are handled, please see varvault.MiniVault and make use of that to ensure that return-variables are handled exactly as you want.

    Note: When this function is called and it finishes, the decorator here will capture the return variables and then store those return variables in the vault with the keys that were passed to the decorator. These variables can then be accessed by another function that uses the same vault-object as this one does.

  4. We then create a new function called use_args that we also annotate with the vault decorator. We pass a different argument to the decorator this time called input_keys. This argument tells the vault which keys in the vault we want passed to this function. The order of the keys doesn't really matter here, the order is mostly aesthetic.

    Note: What ends up happening when this function is called, is that the decorator will try to extract keys defined in input_keys from the vault and then pass those variables to the function as a dictionary (this is what **kwargs essentially is). It is possible to write arguments in the signature of the function itself (in this case the signature would be def use_args(arg1=None, arg2=None), but one of the purposes of the Keyring is that the constants defined in the keyring can be used to easily find where a key is being used. It's recommended to write the function like this but it is possible to write it with pre-defined arguments as well. Do note that the arguments have to have a default value, like None. Otherwise, when you call the function, you have to call the function with the arguments fulfilled as well.

  5. We create a very simple function called run_create_args which doesn't get annotated. This function is simply made to demonstrate what makes this vault so useful. When this function is called, it will obviously call create_args, which will create Keyring.arg1andKeyring.arg2` which will then be stored in the vault.

  6. A final function called run_use_args is then created which calls the use_args function. This function is able to use the arguments defined in create_args because with this vault, the context for where a function runs doesn't really matter as long as the input variables it needs exists in the vault-object already, and the function exists in that scope.

  7. Lastly, the variables that were involved in the execution of this code can be viewed by simply checking the contents of the file ~/.vault/vault.json. In this example the file would simply contain:

    {
      "arg1": 1,
      "arg2": 2
    }
    
  8. When a file such as this (see above) exists, it's very possible to re-create the same vault again from this file. In order to re-create the same vault again simply do this:

    vault = varvault.from_vault_file(Keyring,
                                     "example-vault",
                                     "~/.vault/vault.json",
                                     varvault.VaultFlags.permit_modifications()))
    

    When re-creating a vault from an existing file it's recommended to allow modifications (see varvault.VaultFlags.permit_modifications) in-case you are planning to write the same arguments to the vault again.

Conclusion. This flow demonstrates what this functionality can be used for. With this vault, the context for where a function executes doesn't matter as long as the keys the function needs have been assigned in the vault and the functions exists in the scope. The functions become building blocks that you can call regardless of context provided the above criteria have been met. You don't need to clutter your function calls with tons of input variables because all of that is handled for you by the vault and the decorator. If you use it correctly, you can end up with functions that on the surface appears to not use any arguments or pass any return variables at all. This makes the main body of your code clean and easy to follow. You can then use the Keyring to see where your keys are actually being used. By saving arguments to a file, it allows you to keep parts of the context the code ran in previously. This can be very useful when deploying something which then has to be un-deployed at a later time that isn't necessarily running in the same process as before. This adds an extra layer similar to environment variables that works slightly differently and exclusively in Python. Since the arguments are saved to a JSON file, anything that can parse JSON can obviously use the data as they see fit.

You might also like...
New time-based UUID formats which are suited for use as a database key

uuid6 New time-based UUID formats which are suited for use as a database key. This module extends immutable UUID objects (the UUID class) with the fun

Dynamic key remapper for Wayland Window System, especially for Sway

wayremap Dynamic keyboard remapper for Wayland. It works on both X Window Manager and Wayland, but focused on Wayland as it intercepts evdev input and

A fixture that allows runtime xfail

pytest-runtime-xfail pytest plugin, providing a runtime_xfail fixture, which is callable as runtime_xfail(), to allow runtime decisions to mark a test

Utility to play with ADCS, allows to request tickets and collect information about related objects.

certi Utility to play with ADCS, allows to request tickets and collect information about related objects. Basically, it's the impacket copy of Certify

Import the module and create an object of the class LocalVariable.
Import the module and create an object of the class LocalVariable.

LocalVariable Import the module and create an object of the class LocalVariable. Call the save method with the name and the value of a variable as arg

Create powerful passwords easily and with many options with this program
Create powerful passwords easily and with many options with this program

Password_Generator About the Program: You can create powerful passwords with this program with many options easily! Features: You can copy the generat

This project is a set of programs that I use to create a README.md file.
This project is a set of programs that I use to create a README.md file.

This project is a set of programs that I use to create a README.md file.

Create a Web Component (a Custom Element) from a python file

wyc Create a Web Component (a Custom Element) from a python file (transpile python code to javascript (es2015)). Features Use python to define your cu

🦩 A Python tool to create comment-free Jupyter notebooks.

Pelikan Pelikan lets you convert notebooks to comment-free notebooks. In other words, It removes Python block and inline comments from source cells in

Comments
  • 5.0.0: New major version

    5.0.0: New major version

    Made a ton of changes to the APIs and some new functionality:

    • Reworked how resources function. They now use the same mode as the builtin open function does. You can set modes like "r", "w", "a", "r+", "w+", and "a+". They will work as you expect, with the difference that those with a + indicates live-update is enabled, e.g. "r" is read mode, while "r+" is read with live-update enabled.
    • The standard JsonResource has been changed to create a backup file that is written to. After the backup file has been written to, the name of the file will be changed to the normal file. This way, there's always a file to read from. In very rare cases, if you kill the writing process, there will not be anything in the file since the file is opened in "w" mode, since append mode works really badly with JSON. We might lose a bit of data in such a case, but we retain most of it since we'll read from the standard file that still exists.
    • A Key can now take a set of modifier functions. These work just like validators (see validator.py) in that you create a method to annotate with varvault.modifier() which will allow you to modify the value of the object mapped to the key. This is useful if you want to strip a sequence of characters from a string, or expand vars/user in a path, or to always follow symlinks using os.path.realpath. This can reduce some boilerplate code.
    • The VaultFlags have been changed to just Flags and they have been changed to enums which is quite a bit more lightweight than creating new strings for every key.
    • The factory functions have been completely changed. There is now only create, and no from_vault. The resource object will handle the from_vault case by using append mode (mores "a", or "a+") instead.
    • There's no argument for resource_from or resource_to anymore; just resource. If you want to load a vault from one resource and write to another resource, you'll need to create a resource-object for the resource that you want to load from and load it into the vault manually after creating the vault.
    • A function has been added to utils called assert_and_raise. The function takes a condition as a bool and an exception object. It acts as an assert-function that can raise any exception you want (such as KeyError or ValueError) rather than AssertionError.
    • Internal logging has been changed to be more robust, though this sadly means it's a bit slower. It's not slow, just slower than it was. But the robustness improvements are worth it to get the logging you expect.
    • Added more type-annotations to exposed functions, such as for create under factory.py. This should help users to know how to use the functions better, provided they are using a proper IDE.
    opened by Evixy 0
  • 4.0.0: New major version

    4.0.0: New major version

    New features:

    • Added the possibility to define input keys through the name of the parameters in the signature of the function. It essentially comes down to calling a parameter the same as the name of a key in the keyring and making sure the flag VaultFlags.use_signature_for_input_keys is defined. This can reduce boilerplate, but does make it harder to track the usage of certain keys, which is why it will never be the default behavior of varvault.

    Other changes:

    • Updated the conclusion section of the README.md.
    • Reworked the filehandlers API and simplified the JsonFileHandler slightly.
      • The filehandler now holds the state and keeps track of it, rather than varvault itself keeping track of the state.
    • Made changes to the vaultstructs API to change the name of the abstract method to create which is a lot less cumbersome of a function name.
    • Made significant cleanup of code, mostly in vault.py to make it easier to work with, and to read and comprehend.
    opened by Evixy 0
  • 2.0.0: New major version

    2.0.0: New major version

    • Made changes to allow for the possibility to select a file-handler to write to the vault file, and to implement your own file-handler. If you want to use XML, you can create your own handler for doing that. You need to overload the read/write functions and make them read a dict from the file and write a dict to the file.
    • Removed deprecated vault-flags that were marked for deletion in 2.0.0.
    • Added some new vault-flags, such as a flag for disabling error logging.

    This version is mostly compatible with 1.x but there are some differences that are noteworthy:

    • The signature for vaultfactory.from_vault() has changed to become non-compatible with previous versions. The function enforces a positional argument for the file-handler class, which in most cases will be varvault.FileTypes.JSON. It could be defaulted, but that's not preferable as it becomes inconsistent.
    opened by Evixy 0
Releases(5.0.0)
  • 5.0.0(Dec 11, 2022)

    Made a ton of changes to the APIs and some new functionality:

    • Reworked how resources function. They now use the same mode as the builtin open function does. You can set modes like "r", "w", "a", "r+", "w+", and "a+". They will work as you expect, with the difference that those with a + indicates live-update is enabled, e.g. "r" is read mode, while "r+" is read with live-update enabled.
    • The standard JsonResource has been changed to create a backup file that is written to. After the backup file has been written to, the name of the file will be changed to the normal file. This way, there's always a file to read from. In very rare cases, if you kill the writing process, there will not be anything in the file since the file is opened in "w" mode, since append mode works really badly with JSON. We might lose a bit of data in such a case, but we retain most of it since we'll read from the standard file that still exists.
    • A Key can now take a set of modifier functions. These work just like validators (see validator.py) in that you create a method to annotate with varvault.modifier() which will allow you to modify the value of the object mapped to the key. This is useful if you want to strip a sequence of characters from a string, or expand vars/user in a path, or to always follow symlinks using os.path.realpath. This can reduce some boilerplate code.
    • The VaultFlags have been changed to just Flags and they have been changed to enums which is quite a bit more lightweight than creating new strings for every key.
    • The factory functions have been completely changed. There is now only create, and no from_vault. The resource object will handle the from_vault case by using append mode (mores "a", or "a+") instead.
    • There's no argument for resource_from or resource_to anymore; just resource. If you want to load a vault from one resource and write to another resource, you'll need to create a resource-object for the resource that you want to load from and load it into the vault manually after creating the vault.
    • A function has been added to utils called assert_and_raise. The function takes a condition as a bool and an exception object. It acts as an assert-function that can raise any exception you want (such as KeyError or ValueError) rather than AssertionError.
    • Internal logging has been changed to be more robust, though this sadly means it's a bit slower. It's not slow, just slower than it was. But the robustness improvements are worth it to get the logging you expect.
    • Added more type-annotations to exposed functions, such as for create under factory.py. This should help users to know how to use the functions better, provided they are using a proper IDE.
    Source code(tar.gz)
    Source code(zip)
  • 4.1.0(Sep 1, 2022)

    Made some bugfixes related to resources, where creating a resource that had a relative path to the same directory was not working. It was also not possible to create a vault without supplying a resource which it absolutely should be possible to do.

    Added new functionality to keys, where the usage of a certain key is logged in the key itself. It only logs usage in functions decorated with vaulter for now, but it can be quite helpful when you need to understand why a key is missing in the vault, or if you just want to know where a certain key is used if you are working on a big project.

    Source code(tar.gz)
    Source code(zip)
  • 4.0.1(Aug 26, 2022)

    Fixed a bug related to live-update and vault-structs which meant that specialized keys would not be reloaded as the correct key type. Added a test for this. Also made some fixes to how the state for a resource is handled. Simplified create_mv_from_resource to just take the expected keys as an argument.

    Source code(tar.gz)
    Source code(zip)
  • 4.0.0(Aug 26, 2022)

    New features:

    • Added the possibility to define input keys through the name of the parameters in the signature of the function. It essentially comes down to calling a parameter the same as the name of a key in the keyring and making sure the flag VaultFlags.use_signature_for_input_keys is defined. This can reduce boilerplate, but does make it harder to track the usage of certain keys, which is why it will never be the default behavior of varvault.

    Other changes:

    • Updated the conclusion section of the README.md.
    • Reworked the filehandlers API and simplified the JsonFileHandler slightly.
      • The filehandler now holds the state and keeps track of it, rather than varvault itself keeping track of the state.
    • Made changes to the vaultstructs API to change the name of the abstract method to create which is a lot less cumbersome of a function name.
    • Made significant cleanup of code, mostly in vault.py to make it easier to work with, and to read and comprehend.
    • Renamed filehandler.py to resource.py as that is more what it is than a filehandler, even if that will most likely be what it will be used for.
    Source code(tar.gz)
    Source code(zip)
  • 3.1.0(Aug 8, 2022)

    Made bugfixes for both live-update and filehandlers, which prompted some expansion to the API for the builtin JsonFileHandler: Added a new flag create_file_on_live_update to the JsonFileHandler which essentially creates the file when creating a filehandler that is meant to work with live-update because sometimes you want to create a new vault that is meant to fetch live-update changes later.

    Source code(tar.gz)
    Source code(zip)
  • 3.0.4(Aug 2, 2022)

  • 3.0.3(Aug 1, 2022)

    Made a fix to input_key_can_be_missing when using the vaulter decorator. Due to a recent change in get_multiple, this had to be changed as well so it works as expected. The user still has to make sure the input key that is missing is handled correctly in the decorated function.

    Source code(tar.gz)
    Source code(zip)
  • 3.0.2(Aug 1, 2022)

    Made a fix for the parameter default when using it with get. It had no effect, even when the flag input_key_can_be_missing was configured. Also added a test for this to make sure it works as expected.

    Source code(tar.gz)
    Source code(zip)
  • 3.0.1(Jul 31, 2022)

  • 3.0.0(Jul 31, 2022)

    3.0.0: New major version Significant changes:

    • Made some changes to how filehandlers are handled to make them more customizable to theoretically allow a user to run varvault towards a database.
      • This has caused some APIs to have to change since they didn't make any sense anymore, hence the new major version.
    • Moved validators to a separate new file validators.py since it didn't make much sense to have it in keyrings.py.
    • Scrapped the VaultInterface class. It makes no sense and we don't need it for a user to overload the class, which was its original intent.
    • Removed some functions under utils.py as they don't make sense to have there anymore.
    • Scrapped the constants in class VaultFlags (vaultflags.py) and instead we just use the name of the function as the constant that names the actual flag.
    • Made it so 'build_from_vault_key' in class VaultStructBase (vaultstructs.py) raises NotImplementedError if the function isn't implemented. Python handles abstract classes weirdly when the abstract class also inherits a bultin type (dict, list, float, etc) and allows you to create an instance of a class that doesn't implement all abstract methods, which causes some weird bugs.
    • The JsonFileHandler class has been moved to init.py instead of filehandlers.py.
    Source code(tar.gz)
    Source code(zip)
  • 1.3.0(Feb 15, 2022)

    Added a function called add to MiniVault which essentially wraps the __setitem__ function. This change aims to make it a little bit more easy to add variables to a MiniVault-object.

    Source code(tar.gz)
    Source code(zip)
  • 1.2.1(Dec 21, 2021)

    Made a fix for a bug where if a key was defined without a valid type (i.e. valid_type was set to None), the key could not be parsed from an existing vault file. Also added a test for it.

    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(Dec 18, 2021)

    Added functionality for passing one or more validation functions to a key in a keyring to validate a key in much more detail than just checking that the type is correct.

    For example, it's possible to set up a key whose valid type is int and pass a validation function to the key to validate that the value is an even number. Alternatively, you could validate the length of a list to a certain number of elements, or make sure that a dict-object contains a specific set of keys.

    Source code(tar.gz)
    Source code(zip)
  • 1.1.4(Nov 26, 2021)

    There was a bug with the vaulter function, where returning the values in a minivault would bypass type-validation and you could essentially insert a value of any type for a given key into the vault. This has now been fixed and a test has been implemented for it.

    Source code(tar.gz)
    Source code(zip)
  • 1.1.3(Nov 20, 2021)

    Made a fix to log levels in the vaulter function to make sure that the log levels are always configured in post_call. If a vault was used in nested functions, the inner function would reset the log levels, and then the outer function would keep those log levels. This could cause unintended behavior when using debug flag for example.

    Source code(tar.gz)
    Source code(zip)
  • 1.1.2(Nov 20, 2021)

  • 1.1.1(Nov 20, 2021)

    Created new vault-flags input_key_can_be_missing and clean_return_keys which replaces input_var_can_be_missing and clean_return_var_keys respectively. The name of these new keys makes more sense and matches the rest of the code better.

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Nov 20, 2021)

    Added a new vault flag called return_key_can_be_missing which will allow a vaulter-decorated function to not have to return all keys defined as return-keys. The object returned from the function must be a MiniVault

    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Nov 18, 2021)

Owner
Data Ductus
We turn any changes in IT into a competitive advantage for our clients
Data Ductus
Customized python validations.

A customized python validations.

Wilfred V. Pine 2 Apr 20, 2022
Python lightweight dependency injection library

pythondi pythondi is a lightweight dependency injection library for python Support both sync and async functions Installation pip3 install pythondi Us

Hide 41 Dec 16, 2022
Python HTTP Agent Parser

Features Fast Detects OS and Browser. Does not aim to be a full featured agent parser Will not turn into django-httpagentparser ;) Usage import ht

Shekhar 213 Dec 06, 2022
Dependency Injector is a dependency injection framework for Python.

What is Dependency Injector? Dependency Injector is a dependency injection framework for Python. It helps implementing the dependency injection princi

ETS Labs 2.6k Jan 04, 2023
A collection of common regular expressions bundled with an easy to use interface.

CommonRegex Find all times, dates, links, phone numbers, emails, ip addresses, prices, hex colors, and credit card numbers in a string. We did the har

Madison May 1.5k Dec 31, 2022
Michael Vinyard's utilities

Install vintools To download this package from pypi: pip install vintools Install the development package To download and install the developmen

Michael Vinyard 2 May 22, 2022
A morse code encoder and decoder utility.

morsedecode A morse code encoder and decoder utility. Installation Install it via pip: pip install morsedecode Alternatively, you can use pipx to run

Tushar Sadhwani 2 Dec 25, 2021
Gradually automate your procedures, one step at a time

Gradualist Gradually automate your procedures, one step at a time Inspired by https://blog.danslimmon.com/2019/07/15/ Features Main Features Converts

Ross Jacobs 8 Jul 24, 2022
A tool for testing improper put method vulnerability

Putter-CUP A tool for testing improper put method vulnerability Usage :- python3 put.py -f live-subs.txt Result :- The result in txt file "result.txt"

Zahir Tariq 6 Aug 06, 2021
Macro recording and metaprogramming in Python

macro-kit is a package for efficient macro recording and metaprogramming in Python using abstract syntax tree (AST).

8 Aug 31, 2022
isort is a Python utility / library to sort imports alphabetically, and automatically separated into sections and by type.

isort is a Python utility / library to sort imports alphabetically, and automatically separated into sections and by type. It provides a command line utility, Python library and plugins for various e

Python Code Quality Authority 5.5k Jan 08, 2023
Let's renew the puzzle collection. We'll produce a collection of new puzzles out of the lichess game database.

Let's renew the puzzle collection. We'll produce a collection of new puzzles out of the lichess game database.

Thibault Duplessis 96 Jan 03, 2023
SysInfo is an app developed in python which gives Basic System Info , and some detailed graphs of system performance .

SysInfo SysInfo is an app developed in python which gives Basic System Info , and some detailed graphs of system performance . Installation Download t

5 Nov 08, 2021
An OData v4 query parser and transpiler for Python

odata-query is a library that parses OData v4 filter strings, and can convert them to other forms such as Django Queries, SQLAlchemy Queries, or just plain SQL.

Gorilla 39 Jan 05, 2023
A simple API that will return a key-value pair of randomly generated UUID

A simple API that will return a key-value pair of randomly generated UUID. Key will be a timestamp and value will be UUID. While the server is running, whenever the API is called, it should return al

Pius Lucky 2 Jan 18, 2022
Dill_tils is a package that has my commonly used functions inside it for ease of use.

DilllonB07 Utilities Dill_tils is a package that has my commonly used functions inside it for ease of use. Installation Anyone can use this package by

Dillon Barnes 2 Dec 05, 2021
Tool for generating Memory.scan() compatible instruction search patterns

scanpat Tool for generating Frida Memory.scan() compatible instruction search patterns. Powered by r2. Examples $ ./scanpat.py arm.ks:64 'sub sp, sp,

Ole André Vadla Ravnås 13 Sep 19, 2022
HeadHunter parser

HHparser Description Program for finding work at HeadHunter service Features Find job Parse vacancies Dependencies python pip geckodriver firefox Inst

memphisboy 1 Oct 30, 2021
Run async workflows using pytest-fixtures-style dependency injection

Run async workflows using pytest-fixtures-style dependency injection

Simon Willison 26 Jun 26, 2022
Python USD rate in RUB parser

Python EUR and USD rate parser. Python USD and EUR rate in RUB parser. Parsing i

Andrew 2 Feb 17, 2022