Skip to content
This repository has been archived by the owner on May 13, 2022. It is now read-only.

Commit

Permalink
Merge pull request #164 from golemhq/feature/generate_standalone
Browse files Browse the repository at this point in the history
Feature/generate standalone
  • Loading branch information
luciano-renzi authored Jan 22, 2019
2 parents 4b024c9 + c452930 commit 371182d
Show file tree
Hide file tree
Showing 18 changed files with 308 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ The list of available Golem CLI commands:
**golem-admin createdirectory \<name\>**

Used to generate a new test directory.
Name must be a relative or absolute path for the new test directory. Use '.' to use CWD.


## golem

### run

See [Running Tests](../running-tests.html)
See [Running Tests](running-tests.html)

### gui

Expand Down Expand Up @@ -47,7 +48,8 @@ Creates a new suite inside the given project.

**golem createuser \<username\> \<password\> [-a|--admin -p|--projects -r|--reports]**

Add a new user, projects is a list of projects that the user can access and reports determines which project reports the user can see. In both cases use '*' to give the user access to all projects
Add a new user, projects is a list of projects that the user can access and reports determines which project reports the user can see.
In both cases use '*' to give the user access to all projects

## webdriver-manager

Expand Down
2 changes: 1 addition & 1 deletion docs/source/golem-actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,7 @@ Get search timeout.

Starts an interactive console at this point of the test.
The test should be run with the '-i' flag, otherwise this action will be ignored.
See [Interactive Mode](Interactive-mode.html) for more details.
See [Interactive Mode](interactive-mode.html) for more details.

### random(args)

Expand Down
18 changes: 18 additions & 0 deletions docs/source/golem_public_api/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
API Reference
=================================

.. toctree::
:maxdepth: 1
:glob:

webdriver-class
webelement-class
golem-expected-conditions


.. Indices and tables
.. ==================
.. * :ref:`genindex`
.. * :ref:`modindex`
.. * :ref:`search`
16 changes: 16 additions & 0 deletions docs/source/guides/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Guides
=================================

.. toctree::
:maxdepth: 1
:glob:

standalone-executable


.. Indices and tables
.. ==================
.. * :ref:`genindex`
.. * :ref:`modindex`
.. * :ref:`search`
73 changes: 73 additions & 0 deletions docs/source/guides/standalone-executable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
Generate a Standalone Executable
==================================================

## Using PyInstaller

A Golem standalone executable without any dependencies (including Python) can be generated using [PyInstaller](https://pyinstaller.readthedocs.io/).

Note: the executable must be generated in the same platform that it will be used (e.g.: Windows 10 64 with Python 3.7)

### Steps

Create an empty virtualenv (having the required packages only reduces the final executable size):

```
virtualenv env
```

Clone the repo and install:

```
git clone https://github.com/golemhq/golem.git
cd golem
pip install .
```

Install PyInstaller

```
pip install pyinstaller
```

Install python3-dev if needed (Linux)
```
apt-get install python3-dev
```

Generate the executable

Linux:
```
pyinstaller golem/bin/golem_standalone.py --onefile -n golem --add-data "golem/gui/templates:golem/gui/templates" --add-data "golem/gui/static:golem/gui/static"
```

Windows:
```
pyinstaller golem\bin\golem_standalone.py --onefile -n golem --add-data "golem\gui\templates;golem\gui\templates" --add-data "golem\gui\static;golem\gui\static"
```

Where:

```--onefile``` generates a single file instead of a folder

```-n golem``` is the name of the executable

```--add-data``` includes the templates and static files required by the GUI

The executable is generated in the *dist* folder.


## How to Use the Standalone Executable

Put the executable in your path.

The executable includes the *golem*, *golem-admin*, and *webdriver-manager* interfaces.

Usage:

```
golem golem-admin createdirectory .
golem webdriver-manager update
golem gui
golem run project test
```
10 changes: 4 additions & 6 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,10 @@ Contents
report
settings
golem-test-framework
Interactive-mode
golem_public_api/webdriver-class
golem_public_api/webelement-class
golem_public_api/golem-expected-conditions
golem_public_api/the-cli

interactive-mode
command-line-interface
golem_public_api/index
guides/index

.. Indices and tables
.. ==================
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion golem/bin/golem_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ def main():
print(messages.ADMIN_USAGE_MSG)
elif args.command:
if args.command == 'createdirectory':
commands.createdirectory_command(args.name)
commands.createdirectory_command(args.name, args.no_confirm)
else:
print(messages.ADMIN_USAGE_MSG)
31 changes: 2 additions & 29 deletions golem/bin/golem_init.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,10 @@
"""A CLI script to start golem from any location
"""
"""CLI script to start golem"""
import os
import sys
import subprocess

from golem.main import execute_from_command_line


def main():
# Starting the gui using the console script: 'golem gui'
# won't work in windows there is a bug in windows when
# starting the flask app from a console script
# (setup.py, console_scripts) check out
# https://github.com/pallets/werkzeug/issues/1136
#
# In the meantime, for windows, ensure that the 'golem_start.py'
# file is present otherwise create it first and use it to
# kickstart golem.
# TODO
sys.dont_write_bytecode = True
if os.name == 'nt':
path = os.path.join(os.getcwd(), 'golem_start.py')
if not os.path.isfile(path):
golem_start_py_content = ("import os\n\n"
"from golem.main import execute_from_command_line"
"\n\n"
"if __name__ == '__main__':\n"
" execute_from_command_line(os.getcwd())\n")
with open(path, 'w') as golem_start_file:
golem_start_file.write(golem_start_py_content)

del sys.argv[0]
cmd_list = ['python', 'golem_start.py'] + sys.argv
subprocess.call(cmd_list)
else:
execute_from_command_line(os.getcwd())
execute_from_command_line(os.getcwd())
33 changes: 33 additions & 0 deletions golem/bin/golem_standalone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""Golem standalone script
Use PyInstaller to generate an executable:
pyinstaller golem/bin/golem_standalone.py --distpath . --onefile -n golem
--add-data "golem/gui/templates:golem/gui/templates"
--add-data "golem/gui/static:golem/gui/static"
Note: use `;` (semi-colon) instead of `:` (colon) in Windows
"""
import os
import sys
from multiprocessing import freeze_support

from golem.main import execute_from_command_line
from golem.bin import golem_admin
from webdriver_manager.main import main as webdriver_manager_main
from golem.cli.messages import STANDALONE_USAGE


if __name__ == '__main__':
freeze_support()
if len(sys.argv) > 1:
if sys.argv[1] in ['golem-admin', 'admin']:
del sys.argv[1]
golem_admin.main()
elif sys.argv[1] == 'webdriver-manager':
del sys.argv[1]
webdriver_manager_main()
else:
execute_from_command_line(os.getcwd())
else:
print(STANDALONE_USAGE)
8 changes: 4 additions & 4 deletions golem/cli/argument_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ def get_parser():
parser_createuser = subparsers.add_parser('createuser', add_help=False)
parser_createuser.add_argument('username')
parser_createuser.add_argument('password')
parser_createuser.add_argument('-a', '--admin', action='store_true',
default=False)
parser_createuser.add_argument('-a', '--admin', action='store_true', default=False)
parser_createuser.add_argument('-p', '--projects', nargs='+', default=[])
parser_createuser.add_argument('-r', '--reports', nargs='+', default=[])
parser_createuser.add_argument('-h', '--help', action='store_true')
Expand All @@ -69,9 +68,10 @@ def get_admin_parser():
subparsers = parser.add_subparsers(dest='command')

# createdirectory
parser_createdirectory = subparsers.add_parser('createdirectory',
add_help=False)
parser_createdirectory = subparsers.add_parser('createdirectory', add_help=False)
parser_createdirectory.add_argument('name')
parser_createdirectory.add_argument('-y', '--yes', action='store_true',
default=False, dest='no_confirm')
parser_createdirectory.add_argument('-h', '--help', action='store_true')

return parser
24 changes: 15 additions & 9 deletions golem/cli/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,18 @@ def createuser_command(username, password, is_admin=False,
print('User {} was created successfully'.format(username))


def createdirectory_command(dir_name):
"""Generate a new 'golem' directory"""
if os.path.exists(dir_name):
msg = ('golem-admin createdirectory: error: the directory {} '
'already exists'.format(dir_name))
sys.exit(msg)
else:
destination = os.path.join(os.getcwd(), dir_name)
utils.create_test_dir(destination)
def createdirectory_command(dir_name, no_confirm=False):
"""Create a new Golem test directory
dir_name must be an absolute or relative path.
If the path exists and is not empty and no_confirm
is False the user will be prompted to continue.
"""
abspath = os.path.abspath(dir_name)
if os.path.exists(abspath) and os.listdir(abspath):
# directory is not empty
if not no_confirm:
msg = 'Directory {} is not empty, continue? [Y/n]'.format(dir_name)
if not utils.prompt_yes_no(msg):
return
utils.create_test_dir(abspath)
26 changes: 25 additions & 1 deletion golem/cli/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,32 @@
ADMIN_USAGE_MSG = """
Usage: golem-admin
golem-admin createdirectory <directory-name>
golem-admin createdirectory <directory-name> [-y|--yes]
Create a new directory with the structure and files
required for golem projects.
positional arguments:
directory-name relative or absolute path for the
new test directory. Use '.' to use cwd.
optional arguments:
-y, --yes Do not ask for confirmation
"""


STANDALONE_USAGE = """
Golem Standalone
Includes golem-admin, golem and webdriver-manager interfaces
Example:
golem golem-admin createdirectory <directory-name>
golem webdriver-manager update
golem run <project> <test>
Type the following for more help:
golem golem-admin -h
golem webdriver-manager -h
golem -h
"""
21 changes: 12 additions & 9 deletions golem/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,6 @@ def create_test_dir(workspace):
file_manager.create_directory(path_list=[workspace, 'drivers'],
add_init=False)

golem_start_py_content = ("import os\n\n"
"from golem.main import execute_from_command_line"
"\n\n"
"if __name__ == '__main__':\n"
" execute_from_command_line(os.getcwd())\n")
golem_start_py_path = os.path.join(workspace, 'golem_start.py')
with open(golem_start_py_path, 'a') as golem_start_py_file:
golem_start_py_file.write(golem_start_py_content)

settings_manager.create_global_settings_file(workspace)

users_path = os.path.join(workspace, 'users.json')
Expand Down Expand Up @@ -375,3 +366,15 @@ def get_valid_filename(s):
"""Receives a string and returns a valid filename"""
s = str(s).strip().replace(' ', '_')
return re.sub(r'(?u)[^-\w.]', '', s)


def prompt_yes_no(question, default=True):
"""Prompt the user through the console for yes or no"""
while True:
choice = input(question).lower()
if choice in ['yes', 'y']:
return True
elif choice in ['no', 'n']:
return False
elif not choice:
return default
Loading

0 comments on commit 371182d

Please sign in to comment.