The Python library for Configly: the modern config/static data key/value store.
Configly is the place software developers put their static / config data—like copy, styling, and minor configuration values. They can then update that data directly from https://www.config.ly without having to wait for a deploy process / app store review. Their app or webapp receives the data near instantly. Non-technical folks themselves can publish changes freeing developers to focus on hard software problems and not copy tweaks.
On the backend, Configly provides a read-optimized static-data key/value store built with the aim of being low-latency, and high-availability. The client libraries are made to be dead-simple, lean, and efficient (via enhancements like caching). There is a fancy web UI called the Configulator for setting and updating the configs as well as seeing things like change history. Configly is built for modern software development.
There are a host of other benefits to using Configly ( such as ensuring you do not have data duplicated across clients, reducing load on your primary DB, and better tolerance for traffic spikes), read more about the benefits at Configly.
- API to fetch Strings, JSON Blobs (arrays and objects), Booleans, and Numbers from the Configly backend
- Web interface for modifying these values without having to deploy code (we call our beloved web interface the Configulator).
- High availability, high-throughput, low-latency backend.
- Smart caching on the client libraries to minimize server requests.
- Client libraries available in an expanding amount of languages.
- A Configly account contains a set of Configs.
- A Config is a key-value pair along with associated metadata (like TTL).
- The keys are strings.
- The values are one of the following types:
Type | notes | Example(s) |
---|---|---|
string | "I <3 Configly!" | |
number | Can be integers or decimal; be aware some clients require you to specify which when fetching | 31337, 1.618 |
boolean | only true or false | true, false |
jsonBlob | A JSON5 (more relaxed JSON) array or object. | ["one", 5, true] , {"text": "Buy now!", color: "#0F0"} |
You can make arbitrarily complex JSON structures -- as long as the top level is an object or array. This is incredibly powerful as you can send a host of data with a single config:
A more complex array for a store inventory. Note that because we're using JSON5, quotes are optional for single words.
[
"Simple T-shirt",
"Basic hoodie",
{
item: "Complex T-shirt",
sizes: ['S', 'M', 'L'],
price_us_cents: [1099, 1499, 1599],
}
]
And a more complex object showing how you can internationalize and set style:
{
"welcome_message": {
copy: {
'en': 'Welcome!',
'es': "¡Bienvenidos!",
}, style: {
color: '#0F0',
fontWeight: '700',
}
},
"buy_button" : {
copy: {
'en': 'Buy',
'es': "Comprar",
}, style: {
backgroundColor: "#F00",
border: "border-radius 10px",
}
}
}
In four easy steps!
You'll need a Configly account. Registration is lightning quick—you can register via visiting https://www.config.ly/signup.
After signing up, you can grab your API Key from https://www.config.ly/config. You'll need your API Key to setup the API below.
From https://www.config.ly/config, create a new Config via the "Add" button:
Consider creating a simple JSON Object or Array
Config called greetings
and give it the value of:
['hello', 'hola', '你好', 'नमस्ते']
:
https://www.config.ly/config should look like this:
Be sure to save via clicking 'Send to Clients'. Now, we'll write client code to fetch this key.
pip install configly-python
Add the following code in the execution path of a Python application. It could be a Django or Flask app or a script.
import configly
from configly import errors
configly.api_key = 'YOUR_API_KEY'
try:
greetings_list = configly.get('greetings')
if greetings_list is None:
print('Can\'t find key')
else:
print('Greetings!\n')
for saying in greetings_list:
print(f'A greeting: {saying}')
except errors.InvalidApiKeyError as error:
print(f'Invalid API Key: {error.message}')
except errors.ConfiglyRequestError as error:
print(f'Generic error: {error.message}')
except errors.ConfiglyConnectionError as error:
print(f'Connection error: {error.message}')
# print(error.original_error)
Try changing some values on https://www.config.ly/config to confirm that the client is getting the updates.
Congratulations you have Configly working end-to-end! Now, feel free to use Configly with all your projects!
The golden rule of Configly library use is: do NOT assign the result of a
get()
to a long-lived variable; in order to check for new values from the server, you must callget()
.
The package needs to be configured with your account's API key, which is available in the Configly Configulator
// This value is stored on the Config.ly servers.
store_catalog:
{
has_sale: true,
discount: 0.8,
items: ['T Shirt', 'Hoodie', 'Ferrari'],
price: [100, 250, 200000],
}
On the Python client:
# You can try this example out by setting the `CONFIGLY_API_KEY` environmental variable to our demo account: 'Dem0apiKEY'
try:
catalog = configly.get('store_catalog')
# `get` returns None if the key is not found.
if catalog is None:
print('The key was not found')
else:
items = catalog['items']
prices = catalog['prices']
for index in range(0, len(items)):
item = items[index]
price = prices[index]
if catalog['has_sale']:
price = catalog['discount']*price
print(f'{item}: {price:.2f} USD')
except Exception as error:
print(error)
# configly.errors.InvalidApiKeyError is thrown when there's an unknown API Key
# configly.errors.ConfiglyRequestError is thrown on a timeout or failure to connection to the server
# configly.errors.ConfiglyrequestError is thrown when the server responds with an error
The module must be imported and configured prior to any call to get
.
You can set global options directly on the module. API Key is a required value and the rest are optional.
import configly
configly.api_key = 'YOUR_API_KEY' # Required
# Global Defaults - these are optional and can be overriden per-request.
# Seconds to timeout on requests to the servers
configly.timeout = 3
# Disabling caching will cause the client to ignore server-set TTLs and make a
# a request to Configly's servers on every call to `get` - use this only if
# it is essential that your data is always fresh and you are not worried about
# latency/bandwidth usage.
configly.enable_cache = True
get()
exposes the core function of the library; is to request values stored in Configly.
get()
accepts a string as its first argument‐a key. Configly will fetch the corresponding
value from the Configly servers (or look it up in the local library cache).
hero = configly.get('the_best_superhero')
print(hero)
get
returns None
if the key is not recognized
hero = configly.get('the_best_superhero')
if hero is None:
print('There is no best superhero!')
else:
print(hero)
You can pass per-request values for timeout
and enable_cache
that will
override any global settings set on module first load.
# In this example, it's crucial we have up-to-date data and we're willing wait
# for it (in the case that something goes wrong). Note these overrides are for
# _only_ this call to get()
options = { "timeout": 5, "enable_cache": False }
feature_flag = configly.get("feature1_enabled", options)
if feature_flag:
print("Feature is enabled")
else:
print("Feature is disabled!")
Both options are optional.
get
can throw any of several errors. The errors are in the configly.errors
namespace:
Key | Explanation |
---|---|
InvalidApiKeyError |
Configly's server returned a 401. This likely means the API Key supplied in init() is incorrect. You can see your API Key in the https://config.ly/config. |
ConfiglyConnectionError |
There was a problem communicating with the Config.ly backend. This could be due to a network fault, bad internet connection, or timeout. You can see the original error in the original_error member. Try again later. If the problem persists let us know! |
ConfiglyRequestError |
A miscellaneous error. Take a look at the request value inside the returned object to see the response from Configly's servers. This could indicate a problem with the library; if so, you can create a Github issue and we'll look into it. |
Each error has a message
variable with further details.
try:
copy = configly.get('en_copy')
if copy is None:
print("No copy was found")
else:
print(copy)
except errors.InvalidApiKeyError as error:
print(f"Invalid API Key: {error.message}")
except errors.ConfiglyRequestError as error:
print(f"Generic error: {error.message}")
# You can access the response via error.response
except errors.ConfiglyConnectionError as error:
print(f"Connection error: {error.message}")
# You can access the internal error via original_error
This repository is published under the MIT license.