Skip to content

Commit

Permalink
Ready to release 0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn committed Apr 30, 2018
1 parent 2ccfcd5 commit 1054805
Show file tree
Hide file tree
Showing 14 changed files with 122 additions and 119 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ language: python

python:
- 2.7
- 3.5
- 3.6

install:
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# dump-env changelog

## Version 0.2.0

### Features

- Refactors `Env` class to be a function
- We are now using `python3.5` for tests
- We are now using `md` version of `README` file. New PyPI allows that!
- Updates how linting works


## Version 0.1.1

### Bugfixes:
Expand Down
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
recursive-include dump_env *.py
include LICENSE README.rst
include LICENSE README.md
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# A utility tool to create ``.env`` files

[![Build Status](https://travis-ci.org/sobolevn/dump-env.svg?branch=master)](https://travis-ci.org/sobolevn/dump-env) [![Coverage](https://coveralls.io/repos/github/sobolevn/dump-env/badge.svg?branch=master)](https://coveralls.io/github/sobolevn/dump-env?branch=master) [![Python Version](https://img.shields.io/pypi/pyversions/dump-env.svg)](https://https://pypi.org/project/dump-env/) [![Docs](https://readthedocs.org/projects/dump-env/badge/?version=latest)](http://dump-env.readthedocs.io/en/latest/?badge=latest)

`dump-env` takes an `.env.template` file and some optional environmental variables to create a new `.env` file from these two sources. No external dependencies are used.


## Why?

Why do we need such a tool? Well, this tool is very helpful when your CI is building `docker` (or other) images.
[Previously](https://github.com/wemake-services/wemake-django-template/blob/6a7ab060e8435fd855cd806706c5d1b5a9e76d12/%7B%7Bcookiecutter.project_name%7D%7D/.gitlab-ci.yml#L25) we had some complex logic of encrypting and decrypting files, importing secret keys and so on.
Now we can just create secret variables for our CI, add some prefix to it, and use `dump-env` to make our life easier.


## Quickstart

This quick demo will demonstrate the main and the only purpose of `dump-env`:

```bash
$ dump-env --template=.env.template --prefix='SECRET_ENV_' > .env
```

This command will:

1. take `.env.template`
2. parse its keys and values
3. read and all the variables from the environment starting with `SECRET_ENV_`
4. remove this prefix
5. mix it all together, where environment variables could override ones with the same name from the template
6. sort keys in alphabetic order
7. dump all the keys and values into the `.env` file


## Installation

```bash
$ pip install dump-env
```

## Creating secret variables in some CIs

- `travis`: [docs](https://docs.travis-ci.com/user/environment-variables/#Defining-encrypted-variables-in-.travis.yml)
- `gitlab-ci`: [docs](https://docs.gitlab.com/ce/ci/variables/README.html#secret-variables)
58 changes: 0 additions & 58 deletions README.rst

This file was deleted.

14 changes: 9 additions & 5 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,21 @@
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.viewcode',

# Used to write python docstrings in a readable way:
'sphinxcontrib.napoleon',

# Used to include .md files:
'm2r',
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'

source_suffix = ['.rst', '.md']

# The master toctree document.
master_doc = 'index'
Expand All @@ -62,9 +66,9 @@
# built documents.
#
# The short X.Y version.
version = '0.1.0'
version = '0.2.0'
# The full version, including alpha/beta/rc tags.
release = '0.1.0'
release = '0.2.0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
5 changes: 1 addition & 4 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
dump-env
=====================

.. include:: ../README.rst
.. mdinclude:: ../README.md

API Reference
-------------
Expand Down
3 changes: 2 additions & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# This file is used to setup env
# to generate documentation.

Sphinx==1.6.5
sphinx==1.7.4
sphinx-readable-theme==1.3.0
sphinxcontrib-napoleon==0.6.1
recommonmark==0.4.0
44 changes: 21 additions & 23 deletions dump_env/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,33 @@
from collections import OrderedDict


class Env(object):
def parse(source):
"""
Retrieves option keys from .env files.
Reads the source `.env` file and load key-values.
This module is used just as parser and storage.
"""
Args:
source (str): `.env` template filepath
def __init__(self, source):
"""Reads the source file and load key-values."""
self.source = source
self.data = {}
self._parse()
Returns:
"""
parsed_data = {}

def _parse(self):
with open(self.source) as file_:
for line in file_:
line = line.strip()
with open(source) as file_:
for line in file_:
line = line.strip()

if not line or line.startswith('#') or '=' not in line:
# Ignore comments and lines without assignment.
continue
if not line or line.startswith('#') or '=' not in line:
# Ignore comments and lines without assignment.
continue

# Remove whitespaces and quotes:
key, value = line.split('=', 1)
key = key.strip()
value = value.strip().strip('\'"')
# Remove whitespaces and quotes:
key, value = line.split('=', 1)
key = key.strip()
value = value.strip().strip('\'"')
parsed_data[key] = value

# Store the result:
self.data[key] = value
return parsed_data


def _preload_existing_vars(prefix):
Expand Down Expand Up @@ -75,7 +73,7 @@ def dump(template='', prefix=''):

if template:
# Loading env values from template file:
store.update(Env(template).data)
store.update(parse(template))

# Loading env variables from `os.environ`:
store.update(_preload_existing_vars(prefix))
Expand Down
2 changes: 1 addition & 1 deletion dump_env/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ def main():
variables = dump(args.template, args.prefix)

for key, value in variables.items():
print('{}={}'.format(key, value))
print('{0}={1}'.format(key, value))
19 changes: 11 additions & 8 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
# All plugins and other utils are defined here.

[flake8]
max-complexity = 6
statistics = true
max-line-length = 80
doctests = True

# Flake plugins:
inline-quotes = single
accept-encodings = utf-8


[tool:pytest]
# Flake options:
flake8-statistics = true
flake8-max-line-length = 80
flake8-ignore =
# Disable all pydocstyle checks for tests:
*/tests/*.py D
# Disable some pydocstyle checks:
*.py D100 D104 D106 D401

# Flake plugins:
flake8-inline-quotes = single

# py.test options:
console_output_style = classic
norecursedirs = *.egg .eggs dist build docs .tox .git __pycache__

addopts =
--cache-clear
--flake8
--isort
--cov=dump_env
--cov-report=term
--cov-report=html
-p no:logging


[isort]
Expand Down
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
# Import the README and use it as the long-description.
# Note: this will only work if 'README.rst' is
# present in your MANIFEST.in file!
with io.open(os.path.join(here, 'README.rst'), encoding='utf-8') as f:
with io.open(os.path.join(here, 'README.md'), encoding='utf-8') as f:
long_description = '\n' + f.read()


setup(
name='dump-env',
version='0.1.1',
version='0.2.0',
description='A utility tool to create .env files',
long_description=long_description,
author='Nikita Sobolev',
Expand All @@ -41,6 +41,7 @@
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',
],
Expand Down
29 changes: 14 additions & 15 deletions tests/test_logics.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,32 @@
import pytest

import dump_env
from dump_env import Env, dump
from dump_env import dump, parse


@pytest.fixture(scope='session')
def env(env_file):
return Env(env_file)
@pytest.mark.usefixtures('env_file')
class TestParse(object):
def test_parse_normal(self, env_file):
parsed_data = parse(env_file)

assert isinstance(parsed_data, dict)
assert 'NORMAL_KEY' in parsed_data
assert parsed_data['NORMAL_KEY'] == 'SOMEVALUE'

@pytest.mark.usefixtures('env')
class TestEnv(object):
def test_env_normal(self, env):
assert isinstance(env.data, dict)
assert 'NORMAL_KEY' in env.data
assert env.data['NORMAL_KEY'] == 'SOMEVALUE'
def test_parse_exceptions(self, env_file):
parsed_data = parse(env_file)

def test_env_exceptions(self, env):
assert isinstance(env.data, dict)
assert 'COMMENTED_KEY' not in env.data
assert 'KEY_WITH_NO_ASSIGNMENT' not in env.data
assert isinstance(parsed_data, dict)
assert 'COMMENTED_KEY' not in parsed_data
assert 'KEY_WITH_NO_ASSIGNMENT' not in parsed_data


@pytest.mark.usefixtures('monkeypatch', 'env_file')
class TestDump(object):
@staticmethod
def simple_environ(prefix=''):
return {
'{}key'.format(prefix): 'value',
'{0}key'.format(prefix): 'value',
'a': 'b',
}

Expand Down
6 changes: 5 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py{27,36}
envlist = py{27,35,36}

[testenv]
recreate = False
Expand All @@ -14,6 +14,10 @@ deps =
flake8-comprehensions
flake8-blind-except
flake8-docstrings
flake8-string-format
flake8-coding
flake8-module-name
flake8-pytest
pep8-naming
flake8
pytest-flake8
Expand Down

0 comments on commit 1054805

Please sign in to comment.