Skip to content

Commit a42a73c

Browse files
authored
Feature/packaging (#37)
* Add tox setup POC * Fix syntax to be compatible with Python >= 3.10 * No need to include py3.6 or 3.7 in tox because they reached EOL already * Refactor syntax to be compatible with Python >= 3.9 * Remove no longer needed TODO * Remove py3.8 from tox configuration * Update Github workflow to run test matrix using tox * Update requirements.txt after adding tox * Update pyproject.toml file * Update Github workflow to use pip caching
1 parent dc73116 commit a42a73c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+370
-257
lines changed

.github/actions/setup/action.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: 'Setup'
2+
description: 'Set up Python and install dependencies'
3+
inputs:
4+
python-version:
5+
description: 'Version of Python to set up'
6+
required: true
7+
runs:
8+
using: 'composite'
9+
steps:
10+
- name: Setup Python
11+
uses: actions/setup-python@v4
12+
with:
13+
python-version: ${{ inputs.python-version }}
14+
15+
- name: Restore Dependencies Cache
16+
uses: actions/cache@v3
17+
with:
18+
path: ~/.cache/pip/
19+
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
20+
restore-keys: |
21+
${{ runner.os }}-pip-
22+
23+
- name: Install Dependencies
24+
run: |
25+
pip install --upgrade pip
26+
pip install -r requirements.txt
27+
pip install -e .
28+
shell: bash

.github/workflows/ci.yml

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Unit Tests, Test Coverage, and Pre-Commit Hooks
1+
name: CI
22

33
on:
44
pull_request:
@@ -10,27 +10,49 @@ on:
1010
- closed
1111

1212
jobs:
13-
build:
13+
cache-dependencies:
1414
runs-on: ubuntu-latest
1515
steps:
1616
- uses: actions/checkout@v4
17-
18-
- name: Setup Python
19-
uses: actions/setup-python@v4
17+
- uses: ./.github/actions/setup
2018
with:
21-
python-version: "3.12"
19+
python-version: "3.9"
2220

23-
- name: Install Dependencies
24-
run: |
25-
pip install -e .
26-
pip install -r requirements.txt
27-
pre-commit install
21+
main:
22+
needs: cache-dependencies
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- uses: ./.github/actions/setup
28+
with:
29+
python-version: "3.9"
2830

29-
- name: Run Unit Tests
31+
- name: Unit Tests
3032
run: coverage run -m pytest -s tests
3133

3234
- name: Test Coverage
3335
run: coverage report --fail-under=96
3436

35-
- name: Run Pre-Commit Hooks
36-
run: pre-commit run --all-files
37+
- name: Pre-Commit Hooks
38+
run: |
39+
pre-commit install
40+
pre-commit run --all-files
41+
42+
test-matrix:
43+
needs: cache-dependencies
44+
runs-on: ubuntu-latest
45+
strategy:
46+
matrix:
47+
python-version: [ "3.10", "3.11", "3.12" ]
48+
steps:
49+
- uses: actions/checkout@v4
50+
51+
- uses: ./.github/actions/setup
52+
with:
53+
python-version: ${{ matrix.python-version }}
54+
55+
- name: Run Test Matrix
56+
run: |
57+
pytest -s tests
58+
pre-commit run mypy --all-files

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ __pycache__/
1212

1313
# Coverage.py
1414
.coverage
15+
16+
# Tox
17+
.tox

.pre-commit-config.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ repos:
66
- id: end-of-file-fixer
77
- id: trailing-whitespace
88

9-
# TODO: Add check-hooks-apply and check-useless-excludes
10-
119
- repo: https://github.com/PyCQA/flake8
1210
rev: 6.1.0
1311
hooks:

pyproject.toml

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,37 @@
11
[build-system]
22
requires = ["setuptools>=68.2.2"]
33
build-backend = "setuptools.build_meta"
4+
45
[project]
56
name = "abstract-api"
6-
version = "0.0.1"
7+
version = "1.0.0"
8+
license = {file = "LICENSE"}
79
authors = [
810
{ name="Ebram Shehata", email="ebram96@gmail.com" },
911
]
10-
description = "A Python SDK for using AbstractAPI services"
12+
maintainers = [
13+
{ name="Ebram Shehata", email="ebram96@gmail.com" },
14+
]
15+
keywords = ["sdk", "abstract", "api", "abstract api"]
16+
description = "Python SDK for using AbstractAPI services"
1117
readme = "README.md"
12-
requires-python = ">=3.6"
18+
requires-python = ">=3.9"
1319
classifiers = [
1420
"Programming Language :: Python :: 3",
21+
"Programming Language :: Python :: 3 :: Only",
22+
"Programming Language :: Python :: 3.9",
23+
"Programming Language :: Python :: 3.10",
24+
"Programming Language :: Python :: 3.11",
25+
"Programming Language :: Python :: 3.12",
1526
"License :: OSI Approved :: MIT License",
1627
"Operating System :: OS Independent",
28+
"Intended Audience :: Developers",
29+
]
30+
dependencies = [
31+
"requests>=2.31.0"
1732
]
1833

1934
[project.urls]
20-
"Homepage" = "https://github.com/ebram96/AbstractAPI-Python-SDK"
35+
Homepage = "https://github.com/ebram96/AbstractAPI-Python-SDK"
2136
"Bug Tracker" = "https://github.com/ebram96/AbstractAPI-Python-SDK/issues"
37+
Repository = "https://github.com/ebram96/AbstractAPI-Python-SDK.git"

requirements.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
cachetools==5.3.2
12
certifi==2023.11.17
23
cfgv==3.4.0
4+
chardet==5.2.0
35
charset-normalizer==3.3.2
6+
colorama==0.4.6
47
coverage==7.4.0
58
distlib==0.3.8
9+
exceptiongroup==1.2.0
610
filelock==3.13.1
711
identify==2.5.33
812
idna==3.6
@@ -12,12 +16,14 @@ packaging==23.2
1216
platformdirs==4.1.0
1317
pluggy==1.3.0
1418
pre-commit==3.6.0
19+
pyproject-api==1.6.1
1520
pytest==7.4.4
1621
pytest-mock==3.12.0
1722
PyYAML==6.0.1
1823
requests==2.31.0
1924
requests-mock==1.11.0
20-
setuptools==69.0.3
2125
six==1.16.0
26+
tomli==2.0.1
27+
tox==4.12.0
2228
urllib3==2.1.0
2329
virtualenv==20.25.0

src/abstract_api/avatars/avatars.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import ClassVar
1+
from typing import ClassVar, Optional
22

33
from ..core.bases import BaseService
44
from ..core.exceptions import ClientRequestError
@@ -42,16 +42,16 @@ def _validate_params(**kwargs) -> None:
4242
def create(
4343
self,
4444
name: str,
45-
image_size: int | None = None,
46-
image_format: str | None = None,
47-
font_size: float | None = None,
48-
char_limit: int | None = None,
49-
background_color: str | None = None,
50-
font_color: str | None = None,
51-
is_rounded: bool | None = None,
52-
is_uppercase: bool | None = None,
53-
is_italic: bool | None = None,
54-
is_bold: bool | None = None
45+
image_size: Optional[int] = None,
46+
image_format: Optional[str] = None,
47+
font_size: Optional[float] = None,
48+
char_limit: Optional[int] = None,
49+
background_color: Optional[str] = None,
50+
font_color: Optional[str] = None,
51+
is_rounded: Optional[bool] = None,
52+
is_uppercase: Optional[bool] = None,
53+
is_italic: Optional[bool] = None,
54+
is_bold: Optional[bool] = None
5555
) -> AvatarsResponse:
5656
"""Create a new avatar with the given parameters.
5757

src/abstract_api/company_enrichment/company_enrichment.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import ClassVar, Iterable
1+
from typing import ClassVar, Iterable, Optional
22

33
from ..core.bases import BaseService
44
from ..core.mixins import ResponseFieldsMixin
@@ -25,7 +25,7 @@ class CompanyEnrichment(
2525
def check(
2626
self,
2727
domain: str,
28-
fields: Iterable[str] | None = None
28+
fields: Optional[Iterable[str]] = None
2929
) -> CompanyEnrichmentResponse:
3030
"""Finds a company's details using its domain.
3131
Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from functools import cached_property
2+
from typing import Optional
23

34
from ..core.bases import JSONResponse
45

@@ -7,41 +8,41 @@ class CompanyEnrichmentResponse(JSONResponse):
78
"""Company enrichment service response."""
89

910
@cached_property
10-
def name(self) -> str | None:
11+
def name(self) -> Optional[str]:
1112
"""The name of the company."""
1213
return self._get_response_field("name")
1314

1415
@cached_property
15-
def domain(self) -> str | None:
16+
def domain(self) -> Optional[str]:
1617
"""The domain the company website is hosted on."""
1718
return self._get_response_field("domain")
1819

1920
@cached_property
20-
def year_founded(self) -> int | None:
21+
def year_founded(self) -> Optional[int]:
2122
"""The year the company was founded."""
2223
return self._get_response_field("year_founded")
2324

2425
@cached_property
25-
def industry(self) -> str | None:
26+
def industry(self) -> Optional[str]:
2627
"""The industry the company is operating in."""
2728
return self._get_response_field("industry")
2829

2930
@cached_property
30-
def employees_count(self) -> int | None:
31+
def employees_count(self) -> Optional[int]:
3132
"""The approximate number of employees of the company."""
3233
return self._get_response_field("employees_count")
3334

3435
@cached_property
35-
def locality(self) -> str | None:
36+
def locality(self) -> Optional[str]:
3637
"""The city or region the company headquarter is based in."""
3738
return self._get_response_field("locality")
3839

3940
@cached_property
40-
def country(self) -> str | None:
41+
def country(self) -> Optional[str]:
4142
"""The country the company is based in."""
4243
return self._get_response_field("country")
4344

4445
@cached_property
45-
def linkedin_url(self) -> str | None:
46+
def linkedin_url(self) -> Optional[str]:
4647
"""The LinkedIn URL of the company."""
4748
return self._get_response_field("linkedin_url")

src/abstract_api/core/bases/base_service.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
import os
22
from functools import lru_cache
33
from io import BytesIO
4-
from typing import TYPE_CHECKING, Any, ClassVar, Final, Generic, Type, TypeVar
4+
from typing import (
5+
TYPE_CHECKING,
6+
Any,
7+
ClassVar,
8+
Final,
9+
Generic,
10+
Optional,
11+
Type,
12+
TypeVar
13+
)
514

615
import requests
716
from requests import codes
@@ -34,7 +43,7 @@ class BaseService(Generic[BaseResponseT]):
3443
_service_name_env_var: ClassVar[str]
3544

3645
@classmethod
37-
def _read_api_key_from_env(cls) -> str | None:
46+
def _read_api_key_from_env(cls) -> Optional[str]:
3847
"""Reads service API key from environment variables.
3948
4049
API key exposed as an environment variable must be exposed using a
@@ -50,7 +59,7 @@ def _read_api_key_from_env(cls) -> str | None:
5059
pattern.format(service_name=cls._service_name_env_var)
5160
)
5261

53-
def __init__(self, api_key: str | None = None) -> None:
62+
def __init__(self, api_key: Optional[str] = None) -> None:
5463
"""Constructs a BaseService.
5564
5665
Args:
@@ -80,10 +89,10 @@ def __service_url(self, action: str = "") -> str:
8089
def _service_request(
8190
self,
8291
_response_class: Type[BaseResponseT],
83-
_response_class_kwargs: dict[str, Any] | None = None,
92+
_response_class_kwargs: Optional[dict[str, Any]] = None,
8493
_method: str = "GET",
85-
_body: dict[str, Any] | None = None,
86-
_files: dict[str, BytesIO] | None = None,
94+
_body: Optional[dict[str, Any]] = None,
95+
_files: Optional[dict[str, BytesIO]] = None,
8796
_action: str = "",
8897
**params
8998
) -> BaseResponseT:

0 commit comments

Comments
 (0)