Skip to content

Commit

Permalink
v1.5.3; dependancy and package manager fix
Browse files Browse the repository at this point in the history
  • Loading branch information
amckenna41 committed Mar 12, 2024
1 parent 0663eef commit 4ff077e
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 36 deletions.
13 changes: 5 additions & 8 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ on:
- '**/.yml'
- '**/.ipynb'
- 'docs/**/*'
- .gitignore
- LICENSE
pull_request:
branches: [ main ]

Expand All @@ -21,11 +23,10 @@ jobs:
# test job, waits for build job to complete
test:
name: Setup environment
runs-on: ubuntu-latest
runs-on: ubuntu-latest # os: [ubuntu-latest, macos-latest] #testing on ubuntu and mac os's
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10"] #testing on multiple python versions
# os: [ubuntu-latest, macos-latest] #testing on ubuntu and mac os's
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -41,11 +42,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest
pip install pytest-cov
pip install bandit
pip install safety
pip install codecov
pip install pytest pytest-cov bandit safety codecov
pip install iso3166-2
pip install importlib-metadata
pip install beautifulsoup4
Expand All @@ -68,7 +65,7 @@ jobs:
continue-on-error: true

#unit tests using unittest
- name: Testing with unittest
- name: Running unit tests
run: |
echo "Testing using unittest..."
python3 -m unittest discover tests -v
Expand Down
3 changes: 2 additions & 1 deletion .vercelignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
.github
.githubignore
ToDo.md
tests
tests
/old
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# iso3166-2-api 🌎
# iso3166-2-api 🌎
<!-- ![Vercel](https://vercelbadge.vercel.app/api/amckenna41/iso3166-2-api) -->
![Vercel](https://therealsujitk-vercel-badge.vercel.app/?app=iso3166-2-api)
[![pytest](https://github.com/amckenna41/iso3166-2-api/workflows/Building%20and%20Testing/badge.svg)](https://github.com/amckenna41/iso3166-2-api/actions?query=workflowBuilding%20and%20Testing)
[![iso3166_updates](https://img.shields.io/pypi/v/iso3166-2)](https://pypi.org/project/iso3166-2)
[![iso3166_2](https://img.shields.io/pypi/v/iso3166-2)](https://pypi.org/project/iso3166-2)
[![Documentation Status](https://readthedocs.org/projects/iso3166-2/badge/?version=latest)](https://iso3166-2.readthedocs.io/en/latest/?badge=latest)
[![License: MIT](https://img.shields.io/github/license/amckenna41/iso3166-2)](https://opensource.org/licenses/MIT)
[![Issues](https://img.shields.io/github/issues/amckenna41/iso3166-2-api)](https://github.com/amckenna41/iso3166-2-api/issues)
Expand Down Expand Up @@ -33,7 +33,7 @@ Introduction
------------
This repo contains the front and backend of the API created for the [`iso3166-2`](https://github.com/amckenna41/iso3166-2) repository. The API returns a plethora of subdivison data for all countries in the ISO 3166-2 standard. Utilising the custom-built [`iso3166-2`](https://github.com/amckenna41/iso3166-2) software that incorporates data from the ISO 3166-2. Built using the Python [Flask][flask] framework and hosted on the [Vercel][vercel] platform.

[`iso3166-2`](https://github.com/amckenna41/iso3166-2) is a lightweight custom-built Python package, and accompanying API, that can be used to access all of the world's ISO 3166-2 subdivision data. Here, subdivision can be used interchangably with regions/states/provinces etc. Currently, the package and API support subdivision data from **250** officially assigned code elements within the ISO 3166-1, with **200** of these countries having recognised subdivisions (50 entires have 0 subdivisions), totalling **5,039** subdivisions across the whole dataset. Transitional reservations are not included and only 4 of the exceptional reservations, that have now been officially assigned, are included: AX (Aland Islands), GG (Guernsey), IM (Isle of Man) and JE (Jersey) [[3]](#references). The ISO 3166-2 was first published in 1998 and as of November 2023 there are 5,039 codes defined in it [[2]](#references).
[`iso3166-2`](https://github.com/amckenna41/iso3166-2) is a lightweight custom-built Python package, and accompanying API, that can be used to access all of the world's ISO 3166-2 subdivision data. Here, subdivision can be used interchangably with regions/states/provinces etc. Currently, the package and API support subdivision data from **250** officially assigned code elements within the ISO 3166-1, with **200** of these countries having recognised subdivisions (50 entires have 0 subdivisions), totalling **5,039** subdivisions across the whole dataset. Transitional reservations are not included and only 4 of the exceptional reservations, that have now been officially assigned, are included: AX (Aland Islands), GG (Guernsey), IM (Isle of Man) and JE (Jersey) [[3]](#references). The ISO 3166-2 was first published in 1998 and as of November 2023 there are **5,039** codes defined in it [[2]](#references).

The full list of additional subdivision data attributes supported are:

Expand Down
6 changes: 4 additions & 2 deletions ToDo.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@
- [X] Change /subd to /subdivision
- [X] Update API unit tests.
- [X] Update index.html with new endpoint changes.
- [ ] Update docs with new endpoint changes.
- [X] Update docs with new endpoint changes.
- [ ] Update demo.
- [X] For updated/ alpha endpoint, allow mismtach search of codes.
- [X] Update /alpha error message return.
- [X] Update API.md with example returns.
- [X] Update use of iso3166-2 in index.py.
- [X] Create comment in index.py of the list of endpoints available.
- [ ] Test example links on api homepage work after deployment.
- [X] Test example links on api homepage work after deployment.
- [X] In API, should the overall country code be returned or subdivision code for /subdivison endpoints - do example tests to see how it looks when returned.
- [X] In error handler func, if path has /alpha2 or /alpha3 or /numeric, suggest that endpoints should be /alpha.
- [X] When searching via subd name, lower case, remove spaces, remove accents and any unicode characters.
Expand All @@ -96,6 +96,8 @@
- [X] In /name endpoint, remove repeated references to .lower().replace() etc.
- [X] Change thefuzz scorer ratio.
- [X] In output error message, ensure name is same as input param
- [X] Pull sw version from pypi, similar to how the markdown badges are gotten: [![iso3166_2](https://img.shields.io/pypi/v/iso3166-2)](https://pypi.org/project/iso3166-2/)
- [ ] Need to create a session in selenium to test version of API, since it is dynamically gotten from the software.
<!-- >>> for d in abc.all:
... for e in abc.all[d]:
... if (unidecode(abc.all[d][e]["name"]).lower().replace(' ' ,'') not in new_list):
Expand Down
21 changes: 8 additions & 13 deletions index.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,24 +215,19 @@ def convert_to_alpha2(alpha_code):

#iterate over each input alpha codes, convert to equivalent alpha-2 codes if applicable, return error if invalid code
for code in range(0, len(alpha_code)):
#api can accept numeric code for country, this has to be converted into its alpha-2 counterpart
if (alpha_code[0].isdigit()):
#api can accept alpha-3 or numeric codes for country, this has to be converted into its alpha-2 counterpart
if (len(alpha_code[code]) == 3):
temp_code = convert_to_alpha2(alpha_code[code])
#return error message if invalid alpha-3 code input
if (temp_code is None and alpha_code[0].isdigit()):
error_message["message"] = f"Invalid ISO 3166-1 numeric country code input, cannot convert into corresponding alpha-2 code: {''.join(alpha_code[code])}."
return jsonify(error_message), 400
#return error message if invalid numeric code input
if (temp_code is None):
error_message["message"] = f"Invalid ISO 3166-1 numeric country code input, cannot convert into corresponding alpha-2 code: {''.join(alpha_code[code])}."
error_message["message"] = f"Invalid ISO 3166-2 alpha-3 country code input, cannot convert into corresponding alpha-2 code: {''.join(alpha_code[code])}."
return jsonify(error_message), 400
alpha_code[code] = temp_code
else:
#api can accept 3 letter alpha-3 code for country, this has to be converted into its alpha-2 counterpart
if (len(alpha_code[code]) == 3):
temp_code = convert_to_alpha2(alpha_code[code])
#return error message if invalid alpha-3 code input
if (temp_code is None):
error_message["message"] = f"Invalid ISO 3166-2 alpha-3 country code input, cannot convert into corresponding alpha-2 code: {''.join(alpha_code[code])}."
return jsonify(error_message), 400
alpha_code[code] = temp_code

print("alpha_code[code]", alpha_code[code])
#use regex to validate format of alpha-2 codes - if invalid then return error
if not (bool(re.match(r"^[A-Z]{2}$", alpha_code[code]))) or (alpha_code[code] not in list(iso3166.countries_by_alpha2.keys())):
error_message["message"] = f"Invalid ISO 3166-1 alpha country code input, cannot convert into corresponding alpha-2 code: {''.join(alpha_code[code])}."
Expand Down
29 changes: 27 additions & 2 deletions templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,32 @@

<!-- highlight syntax on page load -->
<script>hljs.initHighlightingOnLoad();</script>
</head>

<!-- pull software version from pypi server -->
<script>
let version = "";

//make get request to pypi json endpoint
fetch("https://pypi.org/pypi/iso3166-2/json")
.then(response => {
if (!response.ok) {
throw new Error("Error making GET request to PyPI server");
}
return response.json();
})
.then(data => {
version = data['info']['version']
})
.catch(error => {
console.error("Error making GET request to PyPI server: ", error);});

//set version to its element after page load
window.onload = function() {
document.getElementById("version").innerHTML = "<b>Version: </b>" + version;
}
</script>

</head>
<!-- left hand menu section -->
<body class="one-content-column-version">
<div class="left-menu">
Expand All @@ -44,7 +68,8 @@
<div class="content-menu">
<div class="content-infos">
<!-- version and last updated info -->
<div class="info" id="version"><b>Version:</b> 1.5.0</div>
<!-- <div class="info" id="version"><b>Version:</b> 1.5.3</div> -->
<div class="info" id="version"></div>
<div class="info" id="last-updated"><b>Last Updated:</b> March 2024</div>
<div class="info" id="author"><b>Developer/Maintainer:</b> <a href="https://github.com/amckenna41/" target="_blank">AJ</a></div>
</div>
Expand Down
16 changes: 9 additions & 7 deletions tests/test_iso3166_2_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import os
from importlib.metadata import metadata
from bs4 import BeautifulSoup
from selenium import webdriver
from requests_html import HTMLSession
import unittest
unittest.TestLoader.sortTestMethodsUsing = None

Expand Down Expand Up @@ -59,14 +61,14 @@ def setUp(self):

def test_homepage_endpoint(self):
""" Testing contents of main /api endpoint that returns the homepage and API documentation. """
test_request_main = requests.get(self.api_base_url, headers=self.user_agent_header)
test_request_main = requests.get(self.api_base_url, headers=self.user_agent_header, timeout=(3.05, 27))
soup = BeautifulSoup(test_request_main.content, 'html.parser')
#1.)
version = soup.find(id='version').text.split(': ')[1]
#1.)
# version = soup.find(id='version').text.split(': ')[1] #need to get this using selenium as version is dynamically retrieved in frontend
last_updated = soup.find(id='last-updated').text.split(': ')[1]
author = soup.find(id='author').text.split(': ')[1]

self.assertEqual(version, "1.5.0", "Expected API version to be 1.5.0, got {}.".format(version))
# self.assertEqual(version, "1.5.3", "Expected API version to be 1.5.3, got {}.".format(version))
self.assertEqual(last_updated, "March 2024", "Expected last updated data to be March 2024, got {}.".format(last_updated))
self.assertEqual(author, "AJ", "Expected author to be AJ, got {}.".format(author))
#2.)
Expand Down Expand Up @@ -373,7 +375,7 @@ def test_alpha_endpoint(self):

self.assertIsInstance(test_request_error2, dict, "Expected output object of API to be type dict, got {}.".format(type(test_request_error2)))
self.assertEqual(len(test_request_error2), 3, "Expected output object of API to be of length 3, got {}.".format(len(test_request_error2)))
self.assertEqual(test_request_error2["message"], "Invalid ISO 3166-1 numeric country code input, cannot convert into corresponding alpha-2 code: {}.".format(test_alpha_error_2),
self.assertEqual(test_request_error2["message"], "Invalid ISO 3166-1 alpha country code input, cannot convert into corresponding alpha-2 code: {}.".format(test_alpha_error_2),
"Error message does not match expected:\n{}".format(test_request_error2["message"]))
self.assertEqual(test_request_error2["path"], self.alpha_base_url + test_alpha_error_2,
"Error path does not match expected:\n{}.".format(test_request_error2["path"]))
Expand Down Expand Up @@ -508,7 +510,7 @@ def test_subdivision_endpoint(self):
"Error status does not match expected:\n{}".format(test_request_xx_yy["status"]))

def test_subdivision_name_endpoint(self):
""" Testing /name endpoint, return all ISO 3166 subdivision data from input subdivision name. """
""" Testing /name endpoint, return all ISO 3166 subdivision data from input subdivision name/names. """
test_subdivision_name_azua = "Azua" #DO-02
test_subdivision_name_cakaudrove = "Cakaudrove" #FJ-03
test_subdivision_name_gelderland_overijssel = "Gelderland, Overijssel" #NL-GE, NL-OV
Expand Down Expand Up @@ -688,7 +690,7 @@ def test_subdivision_name_endpoint(self):
"Error status does not match expected:\n{}".format(test_request_subdivision_error3["status"]))

def test_name_endpoint(self):
""" Testing /country_name endpoint, return all ISO 3166 subdivision data from input alpha-2 name/names. """
""" Testing /country_name endpoint, return all ISO 3166 subdivision data from input country name/names. """
test_country_name_bj = "Benin"
test_country_name_tj = "Tajikistan"
test_country_name_sd = "Sudan"
Expand Down

0 comments on commit 4ff077e

Please sign in to comment.