Coder Social home page Coder Social logo

upersetter's Introduction

upersetter

upersetter helps with automating basic setup tasks for any kind of project in a general way. It provides the ability to describe a project in yaml format and create files and folders based on that.

upersetter uses a full-featured templating engine (jinja2) in order to allow custom variables to be used when creating a new project. It also features an interactive mode to allow guided project creation for end-users.

Learn more about why this project exists and how it is different to e.g. cookiecutter in the section Why another bootstrapping tool. If you are interested in learning more there are examples. which illustrate some usecases.

Installation

upersetter is available on pypi:

pip install upersetter

Dependencies

upersetter has the ability to fetch content from remote sources. This is done via AnyPath Anypath and has the same dependencies as Anypath does for the different protocols.

(upersetter depends on AnyPath but AnyPath does not install any dependencies for the different protocols by default)

Basic Usage

Describing your project can be done either in the form of yaml files or in code as dictionaries.

In the most basic case you describe the structure of your project in a file called structure.yaml:

topfolder:
    :files:
        - afile:
            content: somecontent
    subfolder:
        subsubfolder:
            :files:
                - anotherfile:
                    content: {{anotherfile.content}}

{{anotherfile.content}} is a template expression which can be resolved by specifying the variable antotherfile.content in a options.yaml file:

anotherfile:
    content: Some content for the file

The template expression can also be resolved by interactive usage of upersetter where you can specify the variable on the commandline (see Interactive Usage)

Given you the files structure.yaml and options.yaml are in a folder called /user/example you can execute the following:

python -m upersetter setup folder /user/example

The project will then be created in your current working directory.

In the above example upersetter will create a folder with the name topfolder. Underneath that a file with the name afile and the content somecontent, as well as a folder with the name subfolder will be created. subfolder again has a subfolder subsubfolder which contains the file anotherfile with the content Some content for the file which is specified in the options.yaml file.

However upersetter provides much more dynamic ways to create a project from templates, the commandline or even remote resources.

Advanced usage

Full featured examples can be found in the examples folder which shows usages of all features available.

Structure syntax

A structure file primarily contains two kinds of elements: folders and files

In general the structure file resembles a directory tree, however there is some special syntax to denote how files and folders should be created or filled with content.

In general a structure file looks like this:

<name of folder>:
    <name of subfolder>:
        :files:
            - <name of file>:
                <creation of file: content/template>
    :files:
        - <name of file>:
            <creation of file: content/template>
    <name of second subfolder>:
        :<some_directive>:
            ...

Folders are a dictionary keys in the yaml file. Folders can have files and other folders as sub-entries:

topfolder:
    subfolder:
        ...
another topfolder:
    ...

Files and folders can be created in three different ways - called directives. The following directives are available:

  • :files:
  • :remote:
  • :script:

File creation - The files directive

The files directive creates files either from a template or directly from given content strings. It is indicated with :files:

After that a list of key value pairs representing the filename as the key and the way how to create the file as the value describes the files:

:files:
    - somefile.txt:
        <creation of file: content/template>

Files can be created in the following ways:

content content is the simplest way to create a file. The content of the file is directly specified in the structure file:

:files:
    - somefile.txt:
        content: This is the content of the file.

template template takes the content to be used in a file from a template which is interpreted with the options from the options file:

:files:
    - somefile.txt:
        template: /path/to/the/template.txt

The template name doesn't need to match the name of the file to be created. The template gets rendered with the options as variables and then written to the specified filepath. A full explanation of template-rendering and the options file is given below: `Options and templates`_

Fetching remote resources - The remote directive

The remote directive takes a file or folders from a remote location and copies it in the specified directory. It is indicated with :remote:

remote is always placed directly underneath a folder:

topfolder:
    subfolder:
        :remote: 'ssh://user@host:/home/user'

In this example the folder subfolder will have the contents of the remote folder after upersetter is executed. If the remote is only a file, only that will be copied to the local directory, else the whole directory tree will be copied. The remote handling is done by AnyPath - see there to check out supported protocols from where to fetch remote resources.

Executing external scripts - The scripts directive

The script directive executes a given script in the given directory. It is indicated with :script:

The script itself follows the file directive and can either be created via a template or directly from a string:

topfolder:
    :script:
        from:
          - file_info.py:
              template: file_info.py
        run:
          - python
          - file_info.py

run specifies the actual call of the script, it is a list which will be passed to subprocess and follows the same rules, examples:

['interpreter', 'script', 'arg', 'arg2']
['script', '-arg', 'foo']

Templates within structure files

It is possible to use the full range of template syntax and interpolation within structure files. This allows for example to dynamically specify names of files and folders, to use loops to create files and folders and much more:

{{dynamic_name_of_topfolder}}:
    :files:
        {{dynamic_name_of_file}}

By default a template gets the root scope of the options to evaluate. This means that it has access to everything even if the template evaluation was called from within a template loop. Sometimes it is desirable to pass the current block scope instead of the root - especially if the template is called from within a loop and should access exactly whatever is in the current iteration.

This can be achieved by passing a context:

{% for item in items %} {{item.name}}:
  :files:
    - some_file:
        template: {file: some_template, context: {{item}} }
{% endfor %}

The options file - using templates

tbd

Interactive usage

tbd

Why another bootstrapping tool

upersetter aims to be simple and flexible. Some of the design goals do not align with other projects that solve the same need for setting up folders and files in a reproducible and easy way. This section should explain why another approach was taken and why upersetter exists.

In the python world cookiecutter is a popular project that achieves the same goal as upersetter. It differs in a variety of ways, which makes it suitable for different kind of projects and styles of approaching the problem. If you are not familiar with cookiecutter, check it out and give it a try, it is an amazing project which is very mature (which cannot be said for upersetter as this point)

One of the main differences is that upersetter describes the directory structure in a file. cookiecutter for example uses the filesystem itself and puts placeholders in e.g. folder names. On one hand this makes it easier to see how the result will look like, on the other hand describing the whole structure in a file makes it easier to do things like creating multiple subfolders based on user input.

uppersetter also works with nested input parameters whereas cookiecutter uses flat descriptions.

Contributing

You can contribute in any of the following areas, no matter if it is your first OSS contribution or your thousandths. Contributions are welcome for example: - If you find any issue or bug when using upersetter - If you want to add to the documentation or fix incorrect or missing documentation. - If you want to add features or work on the codebase in general

Just file an issue in the tracker first describing what you would like to do and then create a pull-request.

License

upersetter is licensed under "Mozilla Public License Version 2.0". See LICENSE.txt for the full license.

upersetter's People

Contributors

vaubarth avatar

Watchers

James Cloos avatar

upersetter's Issues

Usage of options within options

Options could be evaluated top to bottom instead of all at once. This would enable us to use template expressions within options. Then we could use the value of an earlier option in a template expression later on in the options itself.

Propper scope for template creation

If a file is being created from a template the template gets the top level scope of the options.
This means that it is not possible to pass scope from a template for loop in the options to the file template:

options.yaml:

languages:
  orig: EN
  to:
    - lang: FR
      translator: Anna
    - lang: DE
      translator: Jörg
    - lang: DK
      translator: Susi

structure.yaml:

{% for language in languages.to %}to_{{language.lang}}:
      files:
        - translator.txt:
            template: translator.txt.tpl
{% endfor %}

Here the template transator.txt.tpl should have language as its scope but gets all of the options, meaning we cannot determine which language this template represents.

Allow parameters as overrides for options in cli

It should be possible to specify parameters on the cli to override any options set.

Example:

python -m upersetter.upersetter setup folder examples/translation_agency/ --param.customer.name=TheCompany --param.project.name=SomeName

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.