diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml new file mode 100644 index 00000000..47cdc57e --- /dev/null +++ b/.github/workflows/pythonapp.yml @@ -0,0 +1,54 @@ +# This is a basic workflow to help you get started with GitHub CI using ActivePython +name: ActivePython application on GitHub CI + +# Setting up Cache directory and ActiveState Platform API key +env: + ACTIVESTATE_CLI_CACHEDIR: ${{ github.workspace }}/.cache + ACTIVESTATE_API_KEY: ${{ secrets.ACTIVESTATE_API_KEY }} + +# Controls when the action will run. Triggers the workflow on push events on the default branch +on: [push] + +# A CI workflow is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on (this one is a matrix build) + runs-on: ${{ matrix.os }} + strategy: + matrix: + # Building on both Windows and Linux(Ubuntu) simultaneously + os: [windows-latest, ubuntu-latest] + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + # Installing State Tool on Windows via Powershell + - name: Install State Tool (Windows) + if: matrix.os == 'windows-latest' + run: | + (New-Object Net.WebClient).DownloadFile('https://platform.activestate.com/dl/cli/install.ps1', 'install.ps1'); + Invoke-Expression -Command "$Env:GITHUB_WORKSPACE\install.ps1 -n -t $Env:GITHUB_WORKSPACE" + echo "::add-path::$Env:GITHUB_WORKSPACE" + # Installing State Tool on Linux with default shell behavior + - name: Install State Tool (Linux) + if: matrix.os != 'windows-latest' + run: sh <(curl -q https://platform.activestate.com/dl/cli/install.sh) -n + # Checking ActiveState Platform for project updates + - name: Update project + run: state pull + # Caching downloaded build using GitHub CI cache + - name: Cache state tool cache + uses: actions/cache@v1 + env: + cache-name: cache-platform-build + with: + path: ${{ env.ACTIVESTATE_CLI_CACHEDIR }} + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('activestate.yaml') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }} + # Execute linting of the project on ActivePython + - name: Lint with flake8 + run: state run lints + # Running project tests using pytest on ActivePython + - name: Test with pytest + run: state run tests diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..d9284955 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,27 @@ +# Use Alpine + glibc image from Docker Hub +image: frolvlad/alpine-glibc + +# Optionally use caching (currenty it slows down instead of speeding up, so not using) +#cache: +# key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG" +# paths: +# - workspace/.state/ + +before_script: +# Install state tool +# - sh <(curl -q https://platform.activestate.com/dl/cli/install.sh) -n +# We need to use the commands below due to install.sh having non-alpine dependencies (no curl) + - wget https://platform.activestate.com/dl/cli/install.sh + - chmod +x ./install.sh + - ./install.sh -n -t /usr/local/bin +# Authenticate with the platform using preset env variable (only required for private projects) +# - state auth +# Download and install the language runtime + - state deploy ActiveState-Labs/learn-python +test: + script: +# Lint code + - pylint src + - flake8 src --statistics --count +# Test code + - pytest diff --git a/.travis.yml b/.travis.yml index b4c45a7e..b13aea76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,13 @@ -language: python -python: - - "3.6" - # Install dependencies. install: - - pip install -r requirements.txt + - sh <(curl -q https://platform.activestate.com/dl/cli/install.sh) -n +before_script: + - state pull # Run linting and tests. script: - - pylint ./src - - flake8 ./src --statistics --count - - pytest + - state run lints + - state run tests # Turn email notifications off. notifications: diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..d87d4199 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,41 @@ +pipeline { + agent any + stages { + stage('Install State Tool') { + steps { + sh '''curl -q https://platform.activestate.com/dl/cli/install.sh -o install.sh +chmod +x install.sh +./install.sh -n -t $WORKSPACE || true''' + } + } + + stage('Authenticate with Platform') { + steps { + sh '$WORKSPACE/state auth --token $ACTIVESTATE_API_KEY' + } + } + + stage('Update Project') { + steps { + sh '$WORKSPACE/state pull' + } + } + + stage('Lint') { + steps { + sh '$WORKSPACE/state run lints' + } + } + + stage('Test') { + steps { + sh '$WORKSPACE/state run tests' + } + } + + } + environment { + SHELL = '/bin/bash' + ACTIVESTATE_API_KEY = credentials('api-key') + } +} \ No newline at end of file diff --git a/README.md b/README.md index f36eb28e..a12dbeda 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,26 @@ +## A fork of the [learn-python](https://github.com/trekhleb/learn-python) project used to explore ways to use the ActiveState Platform and its CLI the State Tool. +If you're here to explore and experiment with he [ActiveState Platform](https://platform.activestate.com/shnewto/learn-python) and its CLI the [State Tool](https://www.activestate.com/products/platform/state-tool), welcome! If you didn't know you were interested but are now, welcome! + +But if you're simply looking to learn python or contribute to the learn-python project, [the original repo](https://github.com/trekhleb/learn-python) is the right place for you. It'll always be up to date, the maintainer is able to tackle issues and PRs, and it for sure deserves all the credit for the value it provides to the community :smile: + + # Playground and Cheatsheet for Learning Python -[![Build Status](https://travis-ci.org/trekhleb/learn-python.svg?branch=master)](https://travis-ci.org/trekhleb/learn-python) +[![Linux Build Status](https://travis-ci.org/shnewto/learn-python.svg?branch=activestate-platform-and-state-tool-setup)](https://travis-ci.org/shnewto/learn-python) +[![Windows Build status](https://ci.appveyor.com/api/projects/status/fgkvuy680gre708t/branch/activestate-platform-and-state-tool-setup?svg=true)](https://ci.appveyor.com/project/shnewto/learn-python/branch/activestate-platform-and-state-tool-setup) +![ActivePython application on GitHub CI](https://github.com/shnewto/learn-python/workflows/ActivePython%20application%20on%20GitHub%20CI/badge.svg) -> This is a collection of Python scripts that are split by [topics](#table-of-contents) and contain +> This is a collection of Python scripts that are split by [topics](#table-of-contents) and contain code examples with explanations, different use cases and links to further readings. -It is a **playground** because you may change or add the code to see how it works -and [test it out](#testing-the-code) using assertions. It also allows you +It is a **playground** because you may change or add the code to see how it works +and [test it out](#testing-the-code) using assertions. It also allows you to [lint the code](#linting-the-code) you've wrote and check if it fits to Python code style guide. -Altogether it might make your learning process to be more interactive and it might help you to keep +Altogether it might make your learning process to be more interactive and it might help you to keep code quality pretty high from very beginning. -It is a **cheatsheet** because you may get back to these code examples once you want to recap the -syntax of [standard Python statements and constructions](#table-of-contents). Also because the +It is a **cheatsheet** because you may get back to these code examples once you want to recap the +syntax of [standard Python statements and constructions](#table-of-contents). Also because the code is full of assertions you'll be able to see expected functions/statements output right away without launching them. @@ -31,14 +39,14 @@ Here might go more detailed explanation of the current topic (i.e. general info def test_list_type(): """Explanation of sub-topic goes here. - + Each file contains test functions that illustrate sub-topics (i.e. lists type, lists methods). """ - + # Here is an example of how to build a list. <-- Comments here explain the action squares = [1, 4, 9, 16, 25] - - # Lists can be indexed and sliced. + + # Lists can be indexed and sliced. # Indexing returns the item. assert squares[0] == 1 # <-- Assertions here illustrate the result. # Slicing returns a new list. @@ -48,10 +56,10 @@ def test_list_type(): So normally you might want to do the following: - [Find the topic](#table-of-contents) you want to learn or recap. -- Read comments and/or documentation that is linked in each script's docstring (as in example above). +- Read comments and/or documentation that is linked in each script's docstring (as in example above). - Look at code examples and assertions to see usage examples and expected output. - Change code or add new assertions to see how things work. -- [Run tests](#testing-the-code) and [lint the code](#linting-the-code) to see if it work and is +- [Run tests](#testing-the-code) and [lint the code](#linting-the-code) to see if it work and is written correctly. ## Table of Contents @@ -107,7 +115,7 @@ written correctly. - [Packages](src/modules/test_packages.py) 8. **Errors and Exceptions** - [Handling Exceptions](src/exceptions/test_handle_exceptions.py) (`try` statement) - - [Raising Exceptions](src/exceptions/test_raise_exceptions.py) (`raise` statement) + - [Raising Exceptions](src/exceptions/test_raise_exceptions.py) (`raise` statement) 9. **Files** - [Reading and Writing](src/files/test_file_reading.py) (`with` statement) - [Methods of File Objects](src/files/test_file_methods.py) @@ -122,6 +130,7 @@ written correctly. - [Dates and Times](src/standard_libraries/test_datetime.py) (`datetime` library) - [Data Compression](src/standard_libraries/test_zlib.py) (`zlib` library) + ## Prerequisites **Installing Python** @@ -129,8 +138,8 @@ written correctly. Make sure that you have [Python3 installed](https://realpython.com/installing-python/) on your machine. You might want to use [venv](https://docs.python.org/3/library/venv.html) standard Python library -to create virtual environments and have Python, pip and all dependent packages to be installed and -served from the local project directory to avoid messing with system wide packages and their +to create virtual environments and have Python, pip and all dependent packages to be installed and +served from the local project directory to avoid messing with system wide packages and their versions. Depending on your installation you might have access to Python3 interpreter either by @@ -153,6 +162,12 @@ Install all dependencies that are required for the project by running: pip install -r requirements.txt ``` +**Alternative approach** + +Have ActiveState's [State Tool](https://www.activestate.com/products/platform/state-tool/)? +- After cloning this repository, just `cd` into it and run `state activate` + + ## Testing the Code Tests are made using [pytest](https://docs.pytest.org/en/latest/) framework. @@ -185,7 +200,7 @@ to [PEP 8](https://www.python.org/dev/peps/pep-0008/) style guide please run: pylint ./src/ ``` -In case if linter will detect error (i.e. `missing-docstring`) you may want to read more about +In case if linter will detect error (i.e. `missing-docstring`) you may want to read more about specific error by running: ```bash diff --git a/activestate.yaml b/activestate.yaml new file mode 100644 index 00000000..2360bf95 --- /dev/null +++ b/activestate.yaml @@ -0,0 +1,8 @@ +project: https://platform.activestate.com/ActiveState-Labs/learn-python +scripts: +- name: tests + description: Executes tests + value: pytest +- name: lints + description: Executes linting tools + value: pylint src && flake8 src --statistics --count diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..4a1d7067 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,16 @@ +version: 1.0.{build} +image: Visual Studio 2019 +init: +- ps: '' +install: +- ps: >- + (New-Object Net.WebClient).DownloadFile('https://platform.activestate.com/dl/cli/install.ps1', 'install.ps1') + + Invoke-Expression "install.ps1 -n" +build_script: +- cmd: state pull +test_script: +- cmd: >- + state run lints + + state run tests diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 00000000..3960af89 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,53 @@ +# Python application example with ActiveState Platform +trigger: +- activestate-platform-and-state-tool-setup +jobs: +- job: Linux + pool: + vmImage: 'ubuntu-latest' + steps: + - script: sh <(curl -q https://platform.activestate.com/dl/cli/install.sh) -n + displayName: 'Install State Tool' + - script: state deploy ActiveState-Labs/learn-python + displayName: 'Deploy project' + - script: pylint src + displayName: 'Lint with pylint' + - script: flake8 src --statistics --count + displayName: 'Lint with flake8' + - script: pytest + displayName: 'Test with pytest' +- job: macOS + pool: + vmImage: 'macOS-latest' + steps: + - script: sh <(curl -q https://platform.activestate.com/dl/cli/install.sh) -n + displayName: 'Install State Tool' + - script: state deploy --force ActiveState-Labs/learn-python + displayName: 'Deploy project' + - script: pylint src + displayName: 'Lint with pylint' + - script: flake8 src --statistics --count + displayName: 'Lint with flake8' + - script: pytest + displayName: 'Test with pytest' +- job: Windows + pool: + vmImage: 'windows-latest' + steps: + - powershell: | + (New-Object Net.WebClient).DownloadFile('https://platform.activestate.com/dl/cli/install.ps1', 'install.ps1') + Invoke-Expression -Command "$env:PIPELINE_WORKSPACE\install.ps1 -n -t $env:AGENT_TOOLSDIRECTORY/bin" + Write-Host "##vso[task.prependpath]$env:AGENT_TOOLSDIRECTORY\bin" + workingDirectory: $(Pipeline.Workspace) + displayName: 'Install State Tool' + - script: | + state deploy ActiveState-Labs/learn-python --path %AGENT_TEMPDIRECTORY% + echo ##vso[task.prependpath]%AGENT_TEMPDIRECTORY%\bin + echo ##vso[task.setvariable variable=PATHEXT]%PATHEXT%;.LNK + displayName: 'Deploy project' + - script: pylint src + displayName: 'Lint with pylint' + - script: flake8 src --statistics --count + displayName: 'Lint with flake8' + - script: pytest + displayName: 'Test with pytest' diff --git a/cloudbuild.yaml b/cloudbuild.yaml new file mode 100644 index 00000000..295fa736 --- /dev/null +++ b/cloudbuild.yaml @@ -0,0 +1,11 @@ +steps: +- name: docker.io/activestate/state_gcb + args: ['state','auth'] +- name: docker.io/activestate/state_gcb + args: ['state', 'deploy', 'ActiveState-Labs/learn-python', '--path', '/workspace/.state'] +- name: docker.io/activestate/state_gcb + args: ['pylint','src'] +- name: docker.io/activestate/state_gcb + args: ['flake8','src','--statistics','--count'] +- name: docker.io/activestate/state_gcb + args: ['pytest'] diff --git a/src/additions/test_pass.py b/src/additions/test_pass.py index 57a6de9b..2654ec72 100644 --- a/src/additions/test_pass.py +++ b/src/additions/test_pass.py @@ -7,6 +7,7 @@ """ +# pylint: disable=unnecessary-pass def test_pass_in_function(): """PASS statement in function @@ -25,7 +26,7 @@ def test_pass_in_loop(): action. For example: """ - # pylint: disable=unused-variable + # pylint: disable=unused-variable, unnecessary-pass for number in range(100): # It just don't do anything but for loop is still valid. pass @@ -37,7 +38,7 @@ def test_pass_in_loop(): # pass # Busy-wait for keyboard interrupt (Ctrl+C) -# pylint: disable=too-few-public-methods +# pylint: disable=too-few-public-methods, unnecessary-pass class MyEmptyClass: """PASS statement in class diff --git a/src/classes/test_instance_objects.py b/src/classes/test_instance_objects.py index e58dc343..7c85c75d 100644 --- a/src/classes/test_instance_objects.py +++ b/src/classes/test_instance_objects.py @@ -17,7 +17,7 @@ def test_instance_objects(): # they are first assigned to. For example, if x is the instance of MyCounter created above, # the following piece of code will print the value 16, without leaving a trace. - # pylint: disable=too-few-public-methods + # pylint: disable=too-few-public-methods, unnecessary-pass class DummyClass: """Dummy class""" pass diff --git a/src/functions/test_function_documentation_string.py b/src/functions/test_function_documentation_string.py index b20d11a9..7e66c6d2 100644 --- a/src/functions/test_function_documentation_string.py +++ b/src/functions/test_function_documentation_string.py @@ -15,6 +15,7 @@ """ +# pylint: disable=unnecessary-pass def do_nothing(): """Do nothing, but document it. diff --git a/src/standard_libraries/test_glob.py b/src/standard_libraries/test_glob.py index c236f73c..ae6d5200 100644 --- a/src/standard_libraries/test_glob.py +++ b/src/standard_libraries/test_glob.py @@ -6,6 +6,7 @@ """ import glob +import os def test_glob(): @@ -15,7 +16,9 @@ def test_glob(): # In some cases (like on Linux Mint, python3.6) the glob() function returns list # in reverse order then it might be expected. Thus lets sort both lists before comparison # using sorted() built-in function. - assert sorted(glob.glob('src/standard_libraries/glob_files/*.txt')) == sorted([ - 'src/standard_libraries/glob_files/first_file.txt', - 'src/standard_libraries/glob_files/second_file.txt' + + path = os.path.join('src', 'standard_libraries', 'glob_files') + assert sorted(glob.glob(os.path.join(path, '*.txt'))) == sorted([ + os.path.join(path, 'first_file.txt'), + os.path.join(path, 'second_file.txt') ])