📜 ⬆️ ⬇️

Fabric - a pair of application recipes

Today, I suddenly realized that scripts are power (after several months of using the fabric ). In fact, 30 minutes spent writing an adequate script eliminates many cumulative hours of repetition of unnecessary actions. To simplify the lives of adept python, there is such an excellent module as fabric . And I want to share a couple of pieces of my fab file as an example of simplifying the developer’s life.

These will be the functions: a “smart” local file commentator and a git commiter.

First of all, put the fabric and, henceforth, put it everywhere (if, all of a sudden, you still do not do that)!

pip install fabric 

Committer


Nothing extraordinary - just a handy recipe:
 # -*- coding: utf-8 -*- from fabric.api import local, prompt, settings env.test_branch = 'test' env.dev_branch = 'dev' def commit(): """  . """ with settings(warn_only=True): local('git status') prompt('Press <Enter> to continue or <Ctrl+C> to cancel.') #    , #         local('git add .') local('git commit') #         def merge_dev_to_test(with_return=True): """       . """ local('git checkout %s' % env.test_branch) #     local('git merge --no-ff %s' % env.dev_branch) #     if with_return: local('git checkout %s' % env.dev_branch) #    def to_test() """     . """ commit() merge_dev_to_test() 

')
The function merge_dev_to_test very applied and it can be easily universalized.

Actually, this skriptik replaces the input of 6 commands, with the input of one fab to_test and the input of a comment in the editor. At the same time, he gives a preview - what changes will occur in the brunch and merges the developments from the development branch into the test one. If the merge is not needed - just perform fab commit .

Commentator


I use it as a switch for Django settings options.

Looking away, I just want to say that this is not the only true way to use different django settings for different situations. This is just one of them. Other options can be found here .

 # -*- coding: utf-8 -*- from os import path from fabric.api import env, local env.settings_files = ( path.join('projcet_root', 'settings.py'), path.join('projcet_root', 'module', 'settings.py'), ) env.settings_versions = { 'develop': '#-D', 'test': '#-T', 'production': '#-P', } def _commenter(c_type, filename, regex, use_sudo=False, char='#', backup='.bak'): """     . """ if use_sudo: sudoer = 'sudo ' else: sudoer = '' if regex.startswith('^'): regex = regex[1:] if regex.endswith('$'): regex = regex[:-1] if c_type == 'comment': replacement = '%s ' % char char = '[^%s ]' % char regex = '(%s.+%s.*)' % (char, regex) else: replacement = '' regex = r'%s ?(.+%s.*)' % (char, regex) local(r"{sudo}sed -i{backup} -r -e 's/^([[:space:]]*){regex}$/" r"\1{replacement}\2/g' {filename}".format(**{ 'sudo': sudoer, 'backup': backup, 'replacement': replacement, 'regex': regex, 'filename': filename, })) def lcomment(*args, **kwargs): """ . """ _commenter('comment', *args, **kwargs) def luncomment(*args, **kwargs): """ . """ _commenter('uncomment', *args, **kwargs) def update_settings(mode): """  . """ for filename in env.settings_files: for version in env.settings_versions: if mode == version: luncomment(filename, versions[version]) elif: lcomment(filename, versions[version]) 


The code is also available in gist .

In the fabric itself, there is a contrib.files module with the comment function, which, by and large, repeats the “commentator” with the difference that it works locally, and comments place not at the beginning of the line, but insert a space between the comment character and the text (like this makes sublime text ) and only looks for a marker at the end of the line.

What he can do. With the fab update_settings:mode=<> command, he has to bypass the files in the env.settings_files list on the way, uncommenting the lines with the marker to the appropriate mode and commenting with the marker that is not appropriate.

Those. calling fab update_settings:mode=test will run through the files /project_root/settings.py and /project_root/module/settings.py commenting on lines ending in '# -D' and '# -P' and uncommenting ending in '# -T' .

What allows to write configurations like:
 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'dvl', # #-D # 'NAME': 'prd', # #-P # 'NAME': 'tst', # #-T 'USER': 'ruutt', 'PASSWORD': 'gigopasswort', 'CHARSET': 'UTF8', }, } 


... sharing them at the commit stage:
 def deploy(branch): env.test_branch =branch #      commit(False) #      ,    update_settings(branch) #        #    , ,   .. local('git checkout %s' % env.dev_branch) #     prompt("OK. Press any <Enter> to exit.") #    IDE     - #             . 


And you can use all this hash so fab deploy:branch=test . Count how many commands in the console and the time spent on them will be saved, I leave to you.

Here is such a time decided to share. And then somehow the fabric is very casually mentioned in the pages of our favorite magazine ...

Source: https://habr.com/ru/post/141271/


All Articles