From d4938d6fcdfef973614559f08f0678a05f022434 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sat, 17 Jun 2023 16:01:50 +0530 Subject: [PATCH 1/7] Rename to python_usernames module --- .bumpversion.cfg | 6 -- .github/workflows/test.yml | 34 +++++++++ .python-version | 1 + .travis.yml | 34 --------- LICENSE | 22 ------ MANIFEST.in | 1 - Makefile | 24 ------- README.md | 25 +++---- pyproject.toml | 67 ++++++++++++++++++ requirements-dev.lock | 19 +++++ requirements.lock | 9 +++ requirements.txt | 4 -- setup.cfg | 12 ---- setup.py | 70 ------------------- .../python_usernames}/__init__.py | 1 - src/python_usernames/reserved_words.py | 19 +++++ src/python_usernames/validators.py | 50 +++++++++++++ .../python_usernames/words.txt | 23 ------ .../{test_usernames.py => test_validators.py} | 3 +- tox.ini | 17 ----- usernames/validators.py | 35 ---------- 21 files changed, 210 insertions(+), 266 deletions(-) delete mode 100644 .bumpversion.cfg create mode 100644 .github/workflows/test.yml create mode 100644 .python-version delete mode 100644 .travis.yml delete mode 100644 LICENSE delete mode 100644 MANIFEST.in delete mode 100644 Makefile create mode 100644 pyproject.toml create mode 100644 requirements-dev.lock create mode 100644 requirements.lock delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 setup.py rename {usernames => src/python_usernames}/__init__.py (75%) create mode 100644 src/python_usernames/reserved_words.py create mode 100644 src/python_usernames/validators.py rename usernames/reserved_words.py => src/python_usernames/words.txt (85%) rename tests/{test_usernames.py => test_validators.py} (96%) delete mode 100644 tox.ini delete mode 100644 usernames/validators.py diff --git a/.bumpversion.cfg b/.bumpversion.cfg deleted file mode 100644 index 797fcc6..0000000 --- a/.bumpversion.cfg +++ /dev/null @@ -1,6 +0,0 @@ -[bumpversion] -current_version = 0.4.1 -commit = True -tag = True - -[bumpversion:file:setup.py] diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..3461b63 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,34 @@ +name: Test + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11"] + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements-dev.lock + + - name: Lint with ruff + run: | + # stop the build if there are Python syntax errors or undefined names + ruff --format=github --select=E9,F63,F7,F82 --target-version=py37 . + # default set of ruff rules with GitHub Annotations + ruff --format=github --target-version=py37 . + - name: Test with pytest + run: | + pytest diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..12398d7 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +cpython@3.11.3 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2cb44c4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -language: python -sudo: false - -python: -- '2.7' -- '3.4' -- '3.5' -- '3.6' -- '3.7' -- '3.8' -- pypy - -install: -- pip install python-coveralls -- pip install -q -r requirements.txt -- pip install --editable . - -before_script: flake8 - -script: -- coverage run --source=usernames/ --omit='*tests*' -m py.test tests/ -v --tb=native -- coverage report - -after_script: -- coveralls - -deploy: - provider: pypi - user: theskumar - password: - secure: DBGKZgPvE9wUsz0PrsB4ooGTqcOpTSsLbwora1JMX1DVB0t5GhGl66CYhouw3hSm3+ud9jZhxn2EAtVPMKQ4XRbfSAlPqg/FhPo+Gn7CpSHz/ZlFGmQ73rL+uKnJi72rP1s9h6xDCJfRt1eoZRNC6KL+7WW5W37KM7TjdVxxMF58FLEEJCZ4GfKf/Vg35ISLKrUtAEmf4nCoNN2UhfYozZ9Yb+2qNwM5yfPEOqHjjfrGbkTA5hvorTg5lZgbl/1xYGvmXb0ep6Aal4wlHi/rS1o+YR+Q/ctmqZ/FFz0Iq+Ky9OUGVkDFgDz29eiLqlZxOM3ciZbZSI708ltchk3dNeluFgzfHD9l6SrzX5rnUm8oZ8Bqmej5lqxbuRfyp2ZRjRcbQP5LfWdiyZ1V0NzySHnKYn9cj4fUqPZPu8nB4y/765dn39QGyJfoWcA+UIrb/4Itn1/cNJ7wXCz2NeuhJJnZHg2RWvnCiSiwOSVcsf+DyjYA2F/17fEKXrwBAt3HiQHwvVE5CNVwNCFP9HSmZjwZw0nBvQio9tPofS4rgTd//Ot4sWcAQG0MI0R3HnvM/xeGEsdSxoO2RCQx9jDxcvI2G0UmnBoO0SuGfozDKZ758s8URsUvOS3hiCrxHmm3rtWVpkb0gpgD2a6U6VeOKAEQHObA2AM73NWb+DF0heE= - on: - tags: true - repo: theskumar/python-usernames diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 1048fb1..0000000 --- a/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Saurabh Kumar - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 0c73842..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -include README.rst LICENSE diff --git a/Makefile b/Makefile deleted file mode 100644 index a31eae4..0000000 --- a/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -.PHONY: clean-pyc clean-build - -clean: clean-build clean-pyc - -clean-build: - rm -fr build/ - rm -fr dist/ - rm -fr *.egg-info - -clean-pyc: - find . -name '*.pyc' -exec rm -f {} + - find . -name '*.pyo' -exec rm -f {} + - find . -name '*~' -exec rm -f {} + - -release: clean sdist - twine check dist/* - twine upload dist/* - -release-test: sdist - twine upload --repository-url https://test.pypi.org/legacy/ dist/* - -sdist: clean - python setup.py sdist bdist_wheel - ls -l dist diff --git a/README.md b/README.md index 1f8f2cc..5f01f1e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -python-usernames -================ +# python-usernames [![Build Status](https://travis-ci.org/theskumar/python-usernames.svg?branch=v0.1.0)](https://travis-ci.org/theskumar/python-usernames) @@ -11,25 +10,22 @@ version](https://badge.fury.io/py/python-usernames.svg)](http://badge.fury.io/py Python library to validate usernames suitable for use in public facing applications where use can choose login names and sub-domains. -Features --------- +## Features - Provides a default regex validator - Validates against list of [banned words](https://github.com/theskumar/python-usernames/blob/master/usernames/reserved_words.py) that should not be used as username. -- Python 2.7, 3.4, 3.5, 3.6, 3.7, 3.8 & pypi +- Python 3.8+ -Installation ------------- +## Installation pip install python-usernames -Usages ------- +## Usages -``` {.sourceCode .python} -from usernames import is_safe_username +```python +from python_usernames import is_safe_username >>> is_safe_username("jerk") False # contains one of the banned words @@ -60,12 +56,12 @@ The default regular expression is as follows: (?= 3.8" + +keywords = [ + 'security', + 'username', + 'validation', + 'user registration', + 'safe', + 'signup', + 'regex', +] + +classifiers=[ + # As from https://pypi.org/classifiers/ + # 'Development Status :: 1 - Planning', + # 'Development Status :: 2 - Pre-Alpha', + # 'Development Status :: 3 - Alpha', + 'Development Status :: 4 - Beta', + # 'Development Status :: 5 - Production/Stable', + # 'Development Status :: 6 - Mature', + # 'Development Status :: 7 - Inactive', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', + 'Intended Audience :: Developers', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: MIT License', + 'Operating System :: OS Independent', + # 'Topic :: System :: Systems Administration', + 'Topic :: Utilities', + 'Topic :: Security', + # 'Environment :: Web Environment', + # 'Framework :: Django', +] + +[project.urls] +Documentation = "https://github.com/theskumar/python-usernames/tree/main#readme" +Source = "https://github.com/theskumar/python-usernames" +Tracker = "https://github.com/theskumar/python-usernames/issues" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.rye] +managed = true +dev-dependencies = [ + "pytest~=7.3.2", + "black~=23.3.0", + "ruff~=0.0.272", +] + +[tool.hatch.metadata] +allow-direct-references = true diff --git a/requirements-dev.lock b/requirements-dev.lock new file mode 100644 index 0000000..f85c8e0 --- /dev/null +++ b/requirements-dev.lock @@ -0,0 +1,19 @@ +# generated by rye +# use `rye lock` or `rye sync` to update this lockfile +# +# last locked with the following flags: +# pre: false +# features: [] +# all-features: false + +-e file:. +black==23.3.0 +click==8.1.3 +iniconfig==2.0.0 +mypy-extensions==1.0.0 +packaging==23.1 +pathspec==0.11.1 +platformdirs==3.5.3 +pluggy==1.0.0 +pytest==7.3.2 +ruff==0.0.272 diff --git a/requirements.lock b/requirements.lock new file mode 100644 index 0000000..aa6be96 --- /dev/null +++ b/requirements.lock @@ -0,0 +1,9 @@ +# generated by rye +# use `rye lock` or `rye sync` to update this lockfile +# +# last locked with the following flags: +# pre: false +# features: [] +# all-features: false + +-e file:. diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index f43a84d..0000000 --- a/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -bumpversion -flake8==2.4.1 -pytest -twine diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index f654e7a..0000000 --- a/setup.cfg +++ /dev/null @@ -1,12 +0,0 @@ -[bdist_wheel] -universal = 1 - -[flake8] -max-line-length = 120 -exclude = .tox,.git,venv,docs - -[metadata] -description_file = README.md - -[tool:pytest] -norecursedirs = .svn _build tmp* dist venv* .git diff --git a/setup.py b/setup.py deleted file mode 100644 index 9f4fd94..0000000 --- a/setup.py +++ /dev/null @@ -1,70 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from setuptools import setup - -with open('README.md') as readme_file: - readme = readme_file.read() - -setup( - name="python-usernames", - description="Python library to validate usernames suitable for use in public facing applications.", - long_description=readme, - long_description_content_type="text/markdown", - version="0.4.1", - author="Saurabh Kumar", - author_email="me+github@saurabh-kumar.com", - url="http://github.com/theskumar/python-usernames", - - packages=[ - str('usernames'), - ], - package_dir={'usernames': 'usernames'}, - include_package_data=True, - zip_safe=False, - license='MIT', - classifiers=[ - # As from https://pypi.python.org/pypi?%3Aaction=list_classifiers - 'Development Status :: 1 - Planning', - # 'Development Status :: 2 - Pre-Alpha', - # 'Development Status :: 3 - Alpha', - # 'Development Status :: 4 - Beta', - # 'Development Status :: 5 - Production/Stable', - # 'Development Status :: 6 - Mature', - # 'Development Status :: 7 - Inactive', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - # 'Programming Language :: Python :: 2.3', - # 'Programming Language :: Python :: 2.4', - # 'Programming Language :: Python :: 2.5', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - # 'Programming Language :: Python :: 3.0', - # 'Programming Language :: Python :: 3.1', - # 'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - # 'Programming Language :: Python :: 3.4', - 'Intended Audience :: Developers', - 'Intended Audience :: System Administrators', - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', - # 'Topic :: System :: Systems Administration', - 'Topic :: Utilities', - # 'Environment :: Web Environment', - # 'Framework :: Django', - ], - keywords=[ - 'username', 'validation', 'registration', 'python', 'safe', 'signup' - ], -) - -# (*) Please direct queries to the discussion group, rather than to me directly -# Doing so helps ensure your question is helpful to other users. -# Queries directly to my email are likely to receive a canned response. -# -# Many thanks for your understanding. diff --git a/usernames/__init__.py b/src/python_usernames/__init__.py similarity index 75% rename from usernames/__init__.py rename to src/python_usernames/__init__.py index 388515f..4a7ecac 100644 --- a/usernames/__init__.py +++ b/src/python_usernames/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from .validators import is_safe_username __all__ = ["is_safe_username"] diff --git a/src/python_usernames/reserved_words.py b/src/python_usernames/reserved_words.py new file mode 100644 index 0000000..9a5aa26 --- /dev/null +++ b/src/python_usernames/reserved_words.py @@ -0,0 +1,19 @@ +""" +List of reserved usernames (pre-defined list of special banned and reserved +keywords in names, such as "root", "www", "admin"). Useful when creating +public systems, where users can choose a login name or a sub-domain name. + +__References:__ +1. http://www.bannedwordlist.com/ +2. http://blog.postbit.com/reserved-username-list.html +3. https://ldpreload.com/blog/names-to-reserve +""" + +import importlib.resources as pkg_resources + + +def get_reserved_words(): + with (pkg_resources.files("python_usernames") / "words.txt").open() as _f: + return set(_f.read().splitlines()) + +__all__ = ["get_reserved_words"] diff --git a/src/python_usernames/validators.py b/src/python_usernames/validators.py new file mode 100644 index 0000000..7adcb7d --- /dev/null +++ b/src/python_usernames/validators.py @@ -0,0 +1,50 @@ +import re + +from .reserved_words import get_reserved_words + + +username_regex = re.compile( + r""" + ^ # beginning of string + (?!_$) # no only _ + (?![-.]) # no - or . at the beginning + (?!.*[_.-]{2}) # no __ or _. or ._ or .. or -- inside + [a-zA-Z0-9_.-]+ # allowed characters, atleast one must be present + (? bool: + # check for max length + if max_length and len(username) > max_length: + return False + + # check against provided regex + if not re.match(regex, username): + return False + + # ensure the word is not in the blacklist and is not a reserved word + if whitelist is None: + whitelist = [] + + if blacklist is None: + blacklist = [] + + default_words = get_reserved_words() + + whitelist = set( + [each_whitelisted_name.lower() for each_whitelisted_name in whitelist] + ) + blacklist = set( + [each_blacklisted_name.lower() for each_blacklisted_name in blacklist] + ) + + default_words = default_words - whitelist + default_words = default_words.union(blacklist) + + return False if username.lower() in default_words else True diff --git a/usernames/reserved_words.py b/src/python_usernames/words.txt similarity index 85% rename from usernames/reserved_words.py rename to src/python_usernames/words.txt index 5311d84..eee9930 100644 --- a/usernames/reserved_words.py +++ b/src/python_usernames/words.txt @@ -1,17 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -""" -List of reserved usernames (pre-defined list of special banned and reserved keywords in names, -such as "root", "www", "admin"). Useful when creating public systems, where users can choose -a login name or a sub-domain name. -__References:__ -1. http://www.bannedwordlist.com/ -2. http://blog.postbit.com/reserved-username-list.html -3. https://ldpreload.com/blog/names-to-reserve -""" - -_d = """ about abuse access @@ -502,12 +488,3 @@ yourname yoursite yourusername -""" - - - -def get_reserved_wordlist(): - return set(_d.splitlines()) - - -__all__ = ["get_reserved_wordlist"] diff --git a/tests/test_usernames.py b/tests/test_validators.py similarity index 96% rename from tests/test_usernames.py rename to tests/test_validators.py index d2f44b2..1e13e7f 100644 --- a/tests/test_usernames.py +++ b/tests/test_validators.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals -from usernames import is_safe_username +from python_usernames import is_safe_username def test_max_lenght(): diff --git a/tox.ini b/tox.ini deleted file mode 100644 index c1f78bb..0000000 --- a/tox.ini +++ /dev/null @@ -1,17 +0,0 @@ -# tox (https://tox.readthedocs.io/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. To use it, "pip install tox" -# and then run "tox" from this directory. - -[tox] -envlist = py27, py34, py35, py36, py37 - -[testenv] -deps = - -commands = - pip install python-coveralls - pip install -q -r requirements.txt - pip install --editable . - python tests/test_usernames.py - diff --git a/usernames/validators.py b/usernames/validators.py deleted file mode 100644 index 4a83fe1..0000000 --- a/usernames/validators.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import re - -from .reserved_words import get_reserved_wordlist - - -username_regex = re.compile( - r""" - ^ # beginning of string - (?!_$) # no only _ - (?![-.]) # no - or . at the beginning - (?!.*[_.-]{2}) # no __ or _. or ._ or .. or -- inside - [a-zA-Z0-9_.-]+ # allowed characters, atleast one must be present - (? max_length: - return False - if not re.match(regex, username): - return False - wordlist = get_reserved_wordlist() - whitelist = set([each_whitelisted_name.lower() for each_whitelisted_name in whitelist]) - blacklist = set([each_blacklisted_name.lower() for each_blacklisted_name in blacklist]) - wordlist = wordlist - whitelist - wordlist = wordlist.union(blacklist) - return False if username.lower() in wordlist else True From ca38932fcb3a90e16ecfb3da068798b09fe1c25e Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sat, 17 Jun 2023 16:29:53 +0530 Subject: [PATCH 2/7] 3.8 compatibility --- .gitignore | 2 ++ src/python_usernames/reserved_words.py | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 4431d1a..ea46ae2 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ __pycache__ .coverage .DS_Store htmlcov/ + +.venv/ diff --git a/src/python_usernames/reserved_words.py b/src/python_usernames/reserved_words.py index 9a5aa26..ccddf9e 100644 --- a/src/python_usernames/reserved_words.py +++ b/src/python_usernames/reserved_words.py @@ -9,11 +9,22 @@ 3. https://ldpreload.com/blog/names-to-reserve """ -import importlib.resources as pkg_resources - +try: + import importlib.resources as pkg_resources +except ImportError: + # Try backported to PY<37 `importlib_resources`. + import importlib_resources as pkg_resources def get_reserved_words(): - with (pkg_resources.files("python_usernames") / "words.txt").open() as _f: - return set(_f.read().splitlines()) + content = '' + # https://stackoverflow.com/questions/6028000/ + try: + with (pkg_resources.files("python_usernames") / "words.txt").open() as _f: + content = _f.read() + except AttributeError: + # Python < PY3.9, fall back to method deprecated in PY3.11. + content = pkg_resources.read_text("python_usernames", 'words.txt') + + return set(content.splitlines()) __all__ = ["get_reserved_words"] From fb504ee95ee7e5cf4b536725590746be8885498e Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sat, 17 Jun 2023 17:19:02 +0530 Subject: [PATCH 3/7] Update wordlist --- src/python_usernames/words.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/python_usernames/words.txt b/src/python_usernames/words.txt index eee9930..db95a52 100644 --- a/src/python_usernames/words.txt +++ b/src/python_usernames/words.txt @@ -38,6 +38,7 @@ avatar backup balls ballsack +banned banner banners bastard @@ -45,6 +46,7 @@ biatch billing bin bitch +blocked blog blogs bloody @@ -124,6 +126,7 @@ end errors events example +exploit fag faq faqs @@ -158,6 +161,7 @@ groups guarantee guest guests +hacker hell help home @@ -173,6 +177,7 @@ html http httpd https +illegal image images imap @@ -274,6 +279,7 @@ nickname nigga nigger no-reply +noaccess nobody noc noreply @@ -286,6 +292,7 @@ ns3 ns4 ntp null +offensive old omg online @@ -341,6 +348,7 @@ purchase pussy python queer +qwerty random redir refund @@ -357,6 +365,7 @@ sale sales sample samples +scammer script scripts scrotum @@ -383,6 +392,7 @@ slut smegma smtp soporte +spammer spunk sql squid @@ -408,6 +418,7 @@ superuser suporte support survey +suspended sync sys sysadmin @@ -430,6 +441,7 @@ test3 teste testimonials tests +testuser theme themes tit @@ -457,6 +469,7 @@ vendas video videos visitor +vulgarity wank web webmail From 85dfcd9d3ab19c3681f3df571f16f259a53e02ae Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sat, 17 Jun 2023 18:24:41 +0530 Subject: [PATCH 4/7] hatch as a dependency --- pyproject.toml | 5 ++++- requirements-dev.lock | 31 ++++++++++++++++++++++++++ src/python_usernames/__about__.py | 1 + src/python_usernames/__init__.py | 2 ++ src/python_usernames/reserved_words.py | 6 +++-- 5 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 src/python_usernames/__about__.py diff --git a/pyproject.toml b/pyproject.toml index 853bcf8..6365610 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,5 @@ [project] name = "python-usernames" -version = "1.0.0" description = "Python library to validate usernames suitable for use in public facing applications." authors = [ { name = "Saurabh Kumar", email = "python-usernames@saurabh-kumar.com" } @@ -61,7 +60,11 @@ dev-dependencies = [ "pytest~=7.3.2", "black~=23.3.0", "ruff~=0.0.272", + "hatch~=1.7.0", ] [tool.hatch.metadata] allow-direct-references = true + +[tool.hatch.version] +path = "src/python_usernames/__about__.py" diff --git a/requirements-dev.lock b/requirements-dev.lock index f85c8e0..f7beb9f 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -7,13 +7,44 @@ # all-features: false -e file:. +anyio==3.7.0 black==23.3.0 +certifi==2023.5.7 click==8.1.3 +distlib==0.3.6 +editables==0.3 +filelock==3.12.2 +h11==0.14.0 +hatch==1.7.0 +hatchling==1.18.0 +httpcore==0.17.2 +httpx==0.24.1 +hyperlink==21.0.0 +idna==3.4 +importlib-metadata==6.6.0 iniconfig==2.0.0 +jaraco-classes==3.2.3 +keyring==23.13.1 +markdown-it-py==3.0.0 +mdurl==0.1.2 +more-itertools==9.1.0 mypy-extensions==1.0.0 packaging==23.1 pathspec==0.11.1 +pexpect==4.8.0 platformdirs==3.5.3 pluggy==1.0.0 +ptyprocess==0.7.0 +pygments==2.15.1 +pyperclip==1.8.2 pytest==7.3.2 +rich==13.4.2 ruff==0.0.272 +shellingham==1.5.0.post1 +sniffio==1.3.0 +tomli-w==1.0.0 +tomlkit==0.11.8 +trove-classifiers==2023.5.24 +userpath==1.8.0 +virtualenv==20.23.1 +zipp==3.15.0 diff --git a/src/python_usernames/__about__.py b/src/python_usernames/__about__.py new file mode 100644 index 0000000..28afc05 --- /dev/null +++ b/src/python_usernames/__about__.py @@ -0,0 +1 @@ +VERSION = "0.4.1" diff --git a/src/python_usernames/__init__.py b/src/python_usernames/__init__.py index 4a7ecac..9ba8c38 100644 --- a/src/python_usernames/__init__.py +++ b/src/python_usernames/__init__.py @@ -1,3 +1,5 @@ from .validators import is_safe_username +__version__ = "0.4.1" + __all__ = ["is_safe_username"] diff --git a/src/python_usernames/reserved_words.py b/src/python_usernames/reserved_words.py index ccddf9e..42762f6 100644 --- a/src/python_usernames/reserved_words.py +++ b/src/python_usernames/reserved_words.py @@ -15,16 +15,18 @@ # Try backported to PY<37 `importlib_resources`. import importlib_resources as pkg_resources + def get_reserved_words(): - content = '' + content = "" # https://stackoverflow.com/questions/6028000/ try: with (pkg_resources.files("python_usernames") / "words.txt").open() as _f: content = _f.read() except AttributeError: # Python < PY3.9, fall back to method deprecated in PY3.11. - content = pkg_resources.read_text("python_usernames", 'words.txt') + content = pkg_resources.read_text("python_usernames", "words.txt") return set(content.splitlines()) + __all__ = ["get_reserved_words"] From 9ad6a317be750979ab34eb2c739b78a98a84dc5f Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sat, 17 Jun 2023 18:30:11 +0530 Subject: [PATCH 5/7] Prepare for v1 release --- pyproject.toml | 1 + src/python_usernames/__about__.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6365610..c69e2e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,6 +8,7 @@ dependencies = [] readme = "README.md" license = "MIT" requires-python = ">= 3.8" +dynamic = ["version"] keywords = [ 'security', diff --git a/src/python_usernames/__about__.py b/src/python_usernames/__about__.py index 28afc05..a29ca52 100644 --- a/src/python_usernames/__about__.py +++ b/src/python_usernames/__about__.py @@ -1 +1 @@ -VERSION = "0.4.1" +VERSION = "1.0.0rc0" From 6125da2ef4eaef41e19b279480159c5ef284e816 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sat, 17 Jun 2023 19:12:31 +0530 Subject: [PATCH 6/7] Add release.yml --- .github/workflows/release.yml | 41 +++++++++++++++++++++++++++++++++++ pyproject.toml | 8 +++++++ 2 files changed, 49 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..fca2d2a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,41 @@ +name: Upload Python Package + +on: + release: + types: [created] + workflow_run: + workflows: ["Test"] + types: + - completed + +jobs: + pypi-publish: + name: upload release to PyPI + + runs-on: ubuntu-latest + # Specifying a GitHub environment is optional, but strongly encouraged + environment: release + permissions: + # IMPORTANT: this permission is mandatory for trusted publishing + id-token: write + + steps: + # retrieve your distributions here + - uses: actions/checkout@v3 + + - name: Set up Python 3.11 + uses: actions/setup-python@v4 + with: + python-version: "3.11" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install hatch + + - name: Build package distributions + run: | + hatch build + + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/pyproject.toml b/pyproject.toml index c69e2e2..3b5cfc3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,5 +67,13 @@ dev-dependencies = [ [tool.hatch.metadata] allow-direct-references = true +[tool.hatch.build.targets.sdist] +include = [ + "/src", +] + +[tool.hatch.build.targets.wheel] +packages = ["src/python_usernames"] + [tool.hatch.version] path = "src/python_usernames/__about__.py" From a3bb55713e7a259075a3a7d5832155652819b7df Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Sat, 17 Jun 2023 19:25:02 +0530 Subject: [PATCH 7/7] Release v1.0.0 --- src/python_usernames/__about__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python_usernames/__about__.py b/src/python_usernames/__about__.py index a29ca52..3277f64 100644 --- a/src/python_usernames/__about__.py +++ b/src/python_usernames/__about__.py @@ -1 +1 @@ -VERSION = "1.0.0rc0" +VERSION = "1.0.0"