diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..8867438 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,66 @@ +name: Bug Report +description: Report broken or incorrect behaviour +labels: bug +body: + - type: markdown + attributes: + value: > + Thank you for taking the time to fill out a bug. + + Please note that this form is for bugs only! + - type: input + attributes: + label: Summary + description: A simple summary of your bug report. + validations: + required: true + - type: textarea + attributes: + label: Reproduction Steps + description: > + What you did to make it happen. + validations: + required: true + - type: textarea + attributes: + label: Minimal Reproducible Code + description: > + A short snippet of code that showcases the bug. + render: python + - type: textarea + attributes: + label: Expected Results + description: > + What did you expect to happen? + validations: + required: true + - type: textarea + attributes: + label: Actual Results + description: > + What actually happened? + validations: + required: true + - type: textarea + attributes: + label: System Information + description: > + Provide some information about your system. + validations: + required: true + - type: checkboxes + attributes: + label: Checklist + description: > + Let's make sure you've properly done due diligence when reporting this issue! + options: + - label: I have searched open issues for duplicates. + required: true + - label: I have shown the entire traceback, if possible. + required: true + - label: I have made sure that this issue is valid. + required: true + - type: textarea + attributes: + label: Additional Context + description: If you have anything else to say, please do so here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..4456673 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Ask a Question + about: Ask questions and have discussions with other users. + url: https://github.com/Pysics/gocomics.py/discussions \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..7ed193b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,38 @@ +name: Feature Request +description: Suggest a feature for this library +labels: enhancement +body: + - type: input + attributes: + label: Summary + description: > + A short summary of what your feature request is. + validations: + required: true + - type: textarea + attributes: + label: The Problem + description: > + What problem is your feature trying to solve? + What becomes easier or possible when this feature is implemented? + validations: + required: true + - type: textarea + attributes: + label: The Ideal Solution + description: > + What is your ideal solution to the problem? + What would you like this feature to do? + validations: + required: true + - type: textarea + attributes: + label: The Current Solution + description: > + What is the current solution to the problem, if any? + validations: + required: false + - type: textarea + attributes: + label: Additional Context + description: If there is anything else to say, please do so here. \ No newline at end of file diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..c39f8ca --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,38 @@ +name: "CodeQL" + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + schedule: + - cron: '22 21 * * 4' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'python' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 \ No newline at end of file diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml new file mode 100644 index 0000000..0ad87c3 --- /dev/null +++ b/.github/workflows/pylint.yml @@ -0,0 +1,23 @@ +name: Pylint + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.8", "3.9", "3.10"] + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pylint + - name: Analysing the code with pylint + run: | + pylint $(git ls-files '*.py') \ No newline at end of file diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 0000000..fe95385 --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,39 @@ +# This workflow will upload a Python Package using Twine when a release is created +# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Upload Python Package + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + deploy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + - name: Build package + run: python -m build + - name: Publish package + uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} \ No newline at end of file diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..1de6bca --- /dev/null +++ b/.pylintrc @@ -0,0 +1,5 @@ +[FORMAT] +max-line-length = 240 + +[MASTER] +disable = R0916, C0116 \ No newline at end of file diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..2374421 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,13 @@ +version: 2 + +build: + os: ubuntu-20.04 + tools: + python: "3.8" + +sphinx: + configuration: docs/conf.py + +python: + install: + - requirements: requirements.txt \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..f95d690 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..74215c3 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include README.md +include LICENSE \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 2c52bef..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# dilbert.py - A basic scraper for Dilbert. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..7e549d5 --- /dev/null +++ b/README.rst @@ -0,0 +1,53 @@ +dilbert.py +=========== + +.. image:: https://img.shields.io/github/license/pysics/dilbert.py + :target: https://github.com/Pysics/dilbert.py/blob/main/LICENSE.md + :alt: license +.. image:: https://img.shields.io/tokei/lines/github/pysics/dilbert.py + :target: https://github.com/Pysics/dilbert.py/graphs/contributors + :alt: lines of code +.. image:: https://img.shields.io/pypi/v/dilbert.py + :target: https://pypi.python.org/pypi/dilbert.py + :alt: PyPI version info +.. image:: https://img.shields.io/pypi/pyversions/dilbert.py + :alt: Python version info + + +Requirements +------------ + +This module requires the following modules: + +* `beautifulsoup4 `_ +* `requests `_ + + +Installation +------------ + +**Python 3.8 or higher is required.** + +To install the stable version, do the following: + +.. code-block:: sh + + # Unix / macOS + python3 -m pip install "dilbert.py" + + # Windows + py -m pip install "dilbert.py" + + +To install the development version, do the following: + +.. code-block:: sh + + $ git clone https://github.com/Pysics/dilbert.py + + +Links +----- + +- `dilbert `_ +- `Documentation `_ \ No newline at end of file diff --git a/dilbert/__init__.py b/dilbert/__init__.py new file mode 100644 index 0000000..59e59c5 --- /dev/null +++ b/dilbert/__init__.py @@ -0,0 +1,20 @@ +""" +Dilbert Scraper +~~~~~~~~~~~~~~~~~~~ + +A basic scraper for Dilbert. + +:copyright: (c) 2022 Omkaar +:license: MIT, see LICENSE for more details. +""" + + +__title__ = "dilbert" +__author__ = "Omkaar" +__license__ = "MIT" +__copyright__ = "Copyright 2022 Omkaar" +__version__ = "1.1.5" + + +from .comic import * +from .utils import * \ No newline at end of file diff --git a/dilbert/comic.py b/dilbert/comic.py new file mode 100644 index 0000000..fe0c984 --- /dev/null +++ b/dilbert/comic.py @@ -0,0 +1,97 @@ +""" +MIT License + +Copyright (c) 2022 Omkaar + +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. +""" + + +from __future__ import annotations + +from datetime import datetime +from urllib.request import Request, urlopen +from typing import Optional + +from bs4 import BeautifulSoup +from requests import get + +from .endpoints import BASE_URL + + +class Comic: + + """ + A class that represents a comic. + + :param date: The comic's date. + :type date: Optional[:class:`datetime`] + + :ivar date: The comic's date. + :ivar image: The URL of the comic's image. + :ivar title: The title of the comic. + :ivar rating: The comic's rating. + :ivar url: The comic's URL. + :ivar tags: The tags associated with the comic. + :ivar transcript: The comic's transcript. + """ + + def __init__(self, date: Optional[datetime] = None) -> None: + + now = datetime.now() + + if (date is not None) and ((now.year < date.year) or (now.year == date.year and now.month < date.month) or (now.year == date.year and now.month == date.month and now.day < date.day)): + raise ValueError("Date must be in the past.") + + self.date = date if date else now + self.url = f"{BASE_URL}strip/{self.date.strftime('%Y-%m-%d')}" + + if not date and get(self.url).url != self.url: + latest = datetime(now.year, now.month, now.day - 1) + self.date = latest + self.url = f"{BASE_URL}strip/{latest.strftime('%Y-%m-%d')}" + + page = Request(self.url) + with urlopen(page) as result: + soup = BeautifulSoup(result.read(), "html.parser") + + tag = soup.find("img", {"class": "img-responsive img-comic"}) + self.image = tag.attrs["src"] + self.title = soup.find("span", {"class": "comic-title-name"}).text.strip() + + if self.title == "": + self.title = None + + formatted_date = self.date.strftime("%Y-%m-%d") + self.rating = float(soup.find("div", {"class": f"comic-rating-{formatted_date}"}).attrs["data-total"]) + + try: + self.tags = soup.find("p", {"class": "small comic-tags"}).text[5:].replace("\n", "").split(",") + for index, element in enumerate(self.tags): + self.tags[index] = element.strip()[1:] + except AttributeError: + self.tags = None + + try: + self.transcript = soup.find("div", {"class": "comic-transcript"}).text[11:] + except AttributeError: + self.transcript = None + + def __eq__(self, __o: Comic) -> bool: + return self.url == __o.url diff --git a/dilbert/endpoints.py b/dilbert/endpoints.py new file mode 100644 index 0000000..d6e6ade --- /dev/null +++ b/dilbert/endpoints.py @@ -0,0 +1,26 @@ +""" +MIT License + +Copyright (c) 2022 Omkaar + +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. +""" + + +BASE_URL = "https://dilbert.com/" \ No newline at end of file diff --git a/dilbert/utils.py b/dilbert/utils.py new file mode 100644 index 0000000..d1dd3c3 --- /dev/null +++ b/dilbert/utils.py @@ -0,0 +1,100 @@ +""" +MIT License + +Copyright (c) 2022 Omkaar + +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. +""" + + +from __future__ import annotations + +from datetime import datetime +from urllib.request import Request, urlopen +from string import ascii_uppercase +from typing import List, Literal, Optional + +from bs4 import BeautifulSoup +from requests.utils import requote_uri + +from .endpoints import BASE_URL +from .comic import Comic + + +def search(text: str, *, month: datetime = None, year: datetime = None, page: Optional[int] = None, sort: Optional[Literal["relevance", "ascending", "descending"]] = "relevance") -> List[Comic]: + """ + Searches Dilbert. + + :param text: The text to search for. + :type text: str + :param category: The category to search in. + :type category: Optional[Literal["comic", "feature"]] + :param page: The page number. + :type page: Optional[:class:`int`] + :param sort: The method of sorting results (based on date). + :type sort: Optional[Literal["ascending", "descending"]] + """ + + def _encode(base: str, parameters: dict) -> str: + url = base + for key, value in parameters.items(): + if value is not None: + url += f"{key}={value}&" + return url[:-1] + + month = month.month if month else None + year = year.year if year else None + + sorts = {"relevance": "relevance", "ascending": "date_asc", "descending": "date_desc"} + parameters = {"terms": text, "page": page, "sort": sorts[sort.lower()], "month": month, "year": year} + url = requote_uri(_encode(f"{BASE_URL}search_results?", parameters)) + + page = Request(url) + with urlopen(page) as result: + soup = BeautifulSoup(result.read(), "html.parser") + + comics = [] + + urls = [tag.attrs["href"] for tag in soup.find_all("a", {"class": "img-comic-link"})] + for url in urls: + comic = Comic(datetime.strptime(url[26:], "%Y-%m-%d")) + comics.append(comic) + + return comics + + +def keywords(letter: str) -> List[str]: + """ + Fetches popular keywords from Dilbert. + + :param letter: The first letter of the keywords. + :type letter: str + """ + letter = letter.upper() + + if letter not in ascii_uppercase: + raise ValueError("'letter' should be a valid alphabet.") + + url = f"{BASE_URL}search/keywords/{letter}" + page = Request(url) + with urlopen(page) as result: + soup = BeautifulSoup(result.read(), "html.parser") + + tags = soup.find_all("ul")[6].text[2:-2].split("\n\n\n") + return tags diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..ab608c4 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,15 @@ +# pylint: skip-file + +import os +import sys + +sys.path.insert(0, os.path.abspath(".")) +sys.path.insert(0, os.path.abspath("..")) + +on_rtd = os.environ.get("READTHEDOCS") == "True" +project = "dilbert.py" +copyright = "2022, Omkaar" +author = "Mr.Brawler" +release = "1.0.0" + +extensions = ["sphinx.ext.autodoc"] \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..2b955a9 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,42 @@ +dilbert.py +========== + +Installation +------------ + +**Python 3.8 or higher is required.** + +To install the stable version, do the following: + +.. code-block:: sh + + # Unix / macOS + python3 -m pip install "dilbert.py" + + # Windows + py -m pip install "dilbert.py" + + +To install the development version, do the following: + +.. code-block:: sh + + $ git clone https://github.com/Pysics/dilbert.py + +Make sure you have the latest version of Python installed, or if you prefer, a Python version of 3.8 or greater. + +If you have have any other issues feel free to search for duplicates and then create a new issue on GitHub with as much detail as possible. Include the output in your terminal, your OS details and Python version. + + +Comic +----- + +.. autoclass:: dilbert.Comic + :members: + + +Other Functions +--------------- + +.. autofunction:: dilbert.search +.. autofunction:: dilbert.keywords \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..1b3a6e8 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1 @@ +sphinx \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..6ae0276 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,23 @@ +[tool.poetry] +name = "dilbert.py" +version = "1.0.0" +description = "Fetch comics from Dilbert." +authors = ["Mr.Brawler "] +license = "MIT" +readme = "README.rst" +repository = "https://github.com/Pysics/dilbert.py/" +documentation = "https://dilbert.readthedocs.io/" +keywords = ["python", "dilbert"] +classifiers = [ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", +] +packages = ["dilbert"] + +[tool.poetry.dependencies] +beautifulsoup4 = "4.11.*" +requests = "2.27.*" + +[tool.poetry.urls] +"Bug Tracker" = "https://github.com/Pysics/dilbert.py/issues" \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e8fe1f6 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +beautifulsoup4 == 4.11.* +requests == 2.28.* \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..2f342d0 --- /dev/null +++ b/setup.py @@ -0,0 +1,28 @@ +from pathlib import Path + +from setuptools import setup + +HERE = Path(__file__).resolve().parent +README = (HERE / "README.rst").read_text() + +setup( + name = "dilbert.py", + version = "1.0.0", + description = "Fetch comics from Dilbert.", + long_description = README, + long_description_content_type = "text/x-rst", + url = "https://github.com/Pysics/dilbert.py", + author = "Omkaar", + author_email = "omkaar.nerurkar@gmail.com", + license = "MIT", + classifiers = [ + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + ], + python_requires='>= 3.8.0', + packages = ["dilbert"], + include_package_data = True, + install_requires = ["beautifulsoup4", "requests"] +) \ No newline at end of file