{ "info": { "author": "Matja\u017e Gu\u0161tin", "author_email": "dev@matjaz.it", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Software Development" ], "description": "Rangeforce: developer-friendly range checks with user-friendly error messages\n===============================================================================\n\n\nEver had to write the same old `if value < 0` bit of Python code to validate\na user input? Tired of not understandable error messages like \n_\"Illegal value\"_?\n\n_Rangeforce_ is a very simple module offering multiple functions checking\nthe range of values, including integers or floats, or lengths of structures \nlike strings or lists. It does so in one line of code while providing an \nunderstandable error message that can be displayed directly to the user.\n\n```python\ndef classic_approach():\n value = int(input('How many hours do you sleep per day? '))\n if value < 0:\n raise ValueError('Hours of sleep must be positive')\n elif value > 24:\n raise ValueError('Hours of sleep must be max 24')\n else:\n return value\n\n# Same code, but simplified using Rangeforce\nimport rangeforce as rf\n\ndef with_rangeforce():\n value = int(input('How many hours do you sleep per day? '))\n return rf.limited(value, 0, 24, 'Hours of sleep') # Magically in 1 line\n```\n\n\nFeatures\n----------------------------------------\n\n- Validate that a value is within a [min, max] interval\n - Including case when min is -infinity and max is +infinity\n - Optional enforcing of the type (e.g. the value must be a float)\n- Functions to validate that a value is an unsigned/signed integer\n that fits into 8/16/32/64 bits, as the C data types\n- Functions to validate positive, negative, non-positive, non-negative integers\n- Validation of the length of an object, either within a [min, max] interval\n or exact length\n- Utility function to clip (limit) a value to fit within a range \n- Customizable name of the variable under validation for the error message \n\n\n\nInstallation\n----------------------------------------\n\n```bash\npip install Rangeforce\n```\n\nor just include the `rangeforce.py` file in your project (copy-paste).\n\n\n\nExample usage\n----------------------------------------\n\n```python\nimport rangeforce as rf\n\nvalue = rf.limited(8000, 20, 5000, dtype=int)\n# If successful, value will held 8000, otherwise (as it would happen in this\n# example) raises a rangeforce.RangeError with a useful message:\n# \"Value must be in range [20, 5000]. 8000 found instead.\"\n# Can be also shown directly to the user:\n\ntry:\n value = rf.limited(8000, 20, 5000, dtype=int)\nexcept rf.RangeError as error:\n print(str(error))\n\n# A missing bound (min or max) means unbounded\nvalue = rf.limited(2000.0, None, 5000.0, dtype=float)\n# Value must be <= 5000 but can be as small as it gets, including negative\n\n\n# Especially useful in setters to validate the input in one line\nclass FullHdPicturesPixel(object):\n def __init__(self, x, y):\n self._x = None\n self._y = None\n self.x = x\n self.y = y\n\n @property\n def x(self):\n return self._x\n\n @x.setter\n def x(self, new_x):\n self._x = rf.limited(new_x, 0, 1920, 'The X pixel coordinate', int)\n\n @property\n def y(self):\n return self._y\n\n @y.setter\n def y(self, new_y):\n self._y = rf.limited(new_y, 0, 1080, 'The Y pixel coordinate', int)\n\npixel = FullHdPicturesPixel(10, 2000)\n# This raises a RangeError with the message:\n# \"The Y pixel coordinate must be in range [0, 1080]. 2000 found instead.\"\n\n\n# Operating with C-like data structures and binary data?\n# These functions might come in handy!\nvalue = rf.int8(20) \nvalue = rf.int16(20) \nvalue = rf.int32(20) \nvalue = rf.int64(20)\nvalue = rf.uint8(20) \nvalue = rf.uint16(20) \nvalue = rf.uint32(20) \nvalue = rf.uint64(20)\n\n# Customize the name of the variable:\ndistance = rf.uint8(-3, 'Distance')\n# This raises a RangeError with the message:\n# \"Distance must be in range [0, 255]. -3 found instead.\"\n\n# To check the length range of anything (e.g. a list or bytes):\nvalue = rf.limited_len([1, 2, 3], 2, 7) # 'value' will hold [1, 2, 3]\n\n# If you need an exact length, do it like this\npair = rf.exact_len([10, 20, 30], 2, name='pair of values')\n# This raises a RangeError with the message:\n# \"Length of pair of values must be exactly 2. 3 found instead.\n```\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/TheMatjaz/Rangeforce", "keywords": "range,domain,limited,validation,user-input,friendly,understandable", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "Rangeforce", "package_url": "https://pypi.org/project/Rangeforce/", "platform": "", "project_url": "https://pypi.org/project/Rangeforce/", "project_urls": { "Homepage": "https://github.com/TheMatjaz/Rangeforce" }, "release_url": "https://pypi.org/project/Rangeforce/1.0.0/", "requires_dist": null, "requires_python": ">=3", "summary": "Developer-friendly range checks with user-friendly error messages", "version": "1.0.0" }, "last_serial": 5601671, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "21b07033ece819e097b07b1e0adada81", "sha256": "0ebb4f4d92ac1cbf66ad7787b78a551210a3f01e3f216b1e478c1e75559c74ec" }, "downloads": -1, "filename": "Rangeforce-1.0.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "21b07033ece819e097b07b1e0adada81", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3", "size": 7109, "upload_time": "2019-07-29T20:19:33", "url": "https://files.pythonhosted.org/packages/28/69/cbd5c805eb3e5e766adc061c10448453925a8e44c40fdc8879fda7266cc6/Rangeforce-1.0.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2d464d6f138b8075a97e411cd0ae0d49", "sha256": "97859ba38fe9f1406fe58448ba55518286ab106361e4c10cf31a9d41cd8f3695" }, "downloads": -1, "filename": "Rangeforce-1.0.0.tar.gz", "has_sig": false, "md5_digest": "2d464d6f138b8075a97e411cd0ae0d49", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3", "size": 9099, "upload_time": "2019-07-29T20:19:36", "url": "https://files.pythonhosted.org/packages/d5/00/ff1efecc2e6bfd43108151e0356cf6da53bc799febfc616b3a2a51d75d12/Rangeforce-1.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "21b07033ece819e097b07b1e0adada81", "sha256": "0ebb4f4d92ac1cbf66ad7787b78a551210a3f01e3f216b1e478c1e75559c74ec" }, "downloads": -1, "filename": "Rangeforce-1.0.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "21b07033ece819e097b07b1e0adada81", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3", "size": 7109, "upload_time": "2019-07-29T20:19:33", "url": "https://files.pythonhosted.org/packages/28/69/cbd5c805eb3e5e766adc061c10448453925a8e44c40fdc8879fda7266cc6/Rangeforce-1.0.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2d464d6f138b8075a97e411cd0ae0d49", "sha256": "97859ba38fe9f1406fe58448ba55518286ab106361e4c10cf31a9d41cd8f3695" }, "downloads": -1, "filename": "Rangeforce-1.0.0.tar.gz", "has_sig": false, "md5_digest": "2d464d6f138b8075a97e411cd0ae0d49", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3", "size": 9099, "upload_time": "2019-07-29T20:19:36", "url": "https://files.pythonhosted.org/packages/d5/00/ff1efecc2e6bfd43108151e0356cf6da53bc799febfc616b3a2a51d75d12/Rangeforce-1.0.0.tar.gz" } ] }