Create a Python library

Written by

1 – Create a new folder

The src folder will contain the source of the project. Inside we create a module called trading_sdk

mkdir -p trading_sdk/src/trading_sdk

1 – Create a file to run the library

def run():
    print("Hello I am a library")


if __name__ == '__main__':
    run()

Create and configure pyproject.toml

Why should i card about pyproject.toml?

Previously, setup.py was used to install a library and its dependencies to be used.

pyproject.toml includes more features than the one described previously.

  • That’s a Python standard and best practice PEP 518
  • It allows to use different build tools than the default setuptools
  • Simplify packaging and distribution of a library
  • Better future compatibility with newest Python versions and standards
# pyproject.toml
[build-system]
requires = [
    "setuptools",  #Use to build python library into a python package
    "wheel",   # Use to distribute packages
]

Push to remote repository

Pypi is the repository where all of the python libraries installed from pip install <package-name> are stored.

Pypi has also a sandbox environment helping you to push your project remotely without needing the approval of pypi for your library to be published

https://test.pypi.org/manage/account/token

Build the module into a package

python -m pip install build
build

Push to Pypi

pip install twine
twine upload -r testpypi dist/trading_sdk-0.0.0.tar.gz

Create a .pypirc file and put in the home folder of your user

[distutils]
index-servers =
    pypi
    testpypi

[pypi]
repository = https://upload.pypi.org/legacy/

[testpypi]
username = __token__
password = ...
repository = https://test.pypi.org/legacy/
twine upload -r testpypi dist/trading_sdk-0.0.0.tar.gz
pip install -i https://test.pypi.org/simple/ trading-sdk==0.0.0

Push to VCS (Version Control Software)

With BitBucket

Create a new repository on bitbucket

git add .
git commit -m ""
git remote add origin bitbucket-repo-git-path
git push

Create a App Password in Bitbucket to allow push/pull for the repository.

Personal Settings

Add a .gitignore

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
# tox aims to automate and standardize testing in Python.
.tox/
# nox is a command-line tool that automates testing in multiple Python environments, similar to tox. Unlike tox, Nox uses a standard Python file for configuration.
.nox/
# Coverage.py is a tool for measuring code coverage of Python programs.
.coverage
.coverage.*
.cache
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
#   For a library or package, you might want to ignore these files since the code is
#   intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# UV
#   Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
#   This is especially recommended for binary packages to ensure reproducibility, and is more
#   commonly ignored for libraries.
#uv.lock

# poetry
#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
#   This is especially recommended for binary packages to ensure reproducibility, and is more
#   commonly ignored for libraries.
#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
#   in version control.
#   https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer developed by Google
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
#  and can be added to the global gitignore or merged into this file.  For a more nuclear
#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# PyPI configuration file
.pypirc

Push to the repository

git init
git add .
git commit -m ""
git branch -m main
git remote add origin <git-repo.git>
git push

To install the library

pip install git+https://bitbucket.org/Aldazar/custom-library.git

Custom pipeline on Bitucket

https://bitbucket.org/bitbucketpipelines/pipelines-guide-python/src/master

# This is an example Starter pipeline configuration
# Use a skeleton to build, test and deploy using manual and parallel steps
# -----
# You can specify a custom docker image from Docker Hub as your build environment.

image: atlassian/default-image:3

pipelines:
  default:
    - parallel:
      - step:
          name: 'Build and Test'
          script:
            - echo "Your build and test goes here..."
      - step:
          name: 'Lint'
          script:
            - echo "Your linting goes here..."
      - step:
          name: 'Security scan'
          script:
            - echo "Your security scan goes here..."

    # The following deployment steps will be executed for each pipeline run. To configure your steps and conditionally deploy see https://support.atlassian.com/bitbucket-cloud/docs/configure-bitbucket-pipelinesyml/
    - step:
        name: 'Deployment to Staging'
        deployment: staging
        script:
          - echo "Your deployment to staging script goes here..."
    - step:
        name: 'Deployment to Production'
        deployment: production
        trigger: 'manual'
        script:
          - echo "Your deployment to production script goes here..."

Security: Install Snyk from Bitbucket to scan files

Security -> Install Snyk

https://bitbucket.org/snyk/snyk-scan/src/develop

Configure a step in Bitbucket pipeline for Snyk

https://www.atlassian.com/devops/security-tutorials/bitbucket-pipelines-snyk

      - step:
          name: 'Security scan'
          caches:
            - node
          script:
            - pipe: snyk/snyk-scan:0.4.3
              variables:
                SNYK_TOKEN: $SNYK_TOKEN
                LANGUAGE: "npm"
                PROJECT_FOLDER: "app/goof"
                TARGET_FILE: "package.json"
                CODE_INSIGHTS_RESULTS: "true"
                SEVERITY_THRESHOLD: "high"
                DONT_BREAK_BUILD: "true"
                MONITOR: "false"

Add repository variables

With Github

Argparse vs Click library

The argparse and click module make it easy to write user-friendly command-line interfaces. Here a comparison of those two libraries.

Ease of UseHighMedium
DependenciesExternal (pip install)None (Standard Library)
Syntax StyleDeclarative (decorators)Imperative
Nested CommandsNative and elegantManual and less intuitive
Validation/PromptingBuilt-inRequires manual handling
Ideal Use CaseComplex tools, developer-friendlySimple, dependency-free tools

Click Library:

Parameter Types:

str / click.STRINGThe default parameter type which indicates unicode strings.
int / click.INTA parameter that only accepts integers.
float / click.FLOATA parameter that only accepts floating point values.
bool / click.BOOLA parameter that accepts boolean values. This is automatically used for boolean flags. The string values “1”, “true”, “t”, “yes”, “y”, and “on” convert to True. “0”, “false”, “f”, “no”, “n”, and “off” convert to False.
click.UUIDA parameter that only accepts integers.
click.DateTimeThe DateTime type converts date strings into datetime objects.
click.ChoiceThe choice type allows a value to be checked against a fixed set of supported values. All of these values have to be strings.
click.IntRangeRestrict an click.INT value to a range of accepted values with min, max params.
click.FloatRangeRestrict a click.FLOAT value to a range of accepted values with min, max params

For more information about available click types: https://click.palletsprojects.com/en/stable/parameters/#parameter-types

import click
from pkg_resources import require


@click.command()
# @click.argument('name')
@click.option('-n', '--name', required=True)
@click.option('-p', '--password', prompt='Password', help='The person to greet.')
def run(name, password):
    print(f"Hello I am a {name}")




if __name__ == '__main__':
    run()

Library Versioning

pip install bumpver
#[build-system]
#requires = [
#    "setuptools",  #Use to build python library into a python package
#    "wheel",   # Use to distribute packages
#]
[build-system]
requires = ["setuptools>=61.0.0", "setuptools-scm"]

[project]
name = "trading_sdk"
dynamic = ["version"] # version is provided later and not fixed

[tool.setuptools.dynamic]
version = {attr = "trading_sdk.__version__"}

[tool.bumpver.tagging]
# Configuration for creating Git tags
tag_name_template = "v{new_version}"
annotate = true

[tool.bumpver]
current_version = "0.1.2"
version_pattern = "MAJOR.MINOR.PATCH"

[tool.bumpver.file_patterns]
"pyproject.toml" = [
    'current_version = "{version}"',
]
"src/trading_sdk/__init__.py" = [
    '__version__ = "{version}"'
]
"README.md" = [
    "# Trading SDK {version}",
]
bumpver test 0.0.1 "MAJOR.MINOR.PATCH" --patch
bumpver update -h # help
bumpver update -p # increase patch version
bumpver update -m # increase minor version
bumpver update --major # increase major version