Commit a08baec2 authored by AntonKras's avatar AntonKras
Browse files

Добавлен README

parent 403bd37d
Вэб-сервис short_url_generator осуществляет работу с короткими ссылками.
Короткая и длинная ссылка имеют вид "ah712: yandex.ru" и записаны в файле формата yml.
**Пример:**
Если осуществляется запрос GET от вебсервиса по пути /ah712,то происходит redirect на Яндекс.
Также возможно добавления своих соответствий с помощью формы.
**Запуск**
Для запуска программы необходимо прописать
`python app.py путь к файлу формата .yml или .yaml, в котором прописаны соответствия {short_url: long_url}`
`также необходимо запустить сервер redis`
**Функции:**
- main - функция рендерит index.html;
- add - функция добавляет новое соответствие;
- redirect_somewhere - функция осуществляет перенаправление в зависимости от соответствия {short_url: long_url}.
Возвращает 404, если соответствия не существует;
- extract_data_from_yml - функция извлекает данные из yml файла;
- generate_short_url - функция генерирует короткий url;
- check_if_input_is_url - функция проверяет является ли ссылка ссылкой;
- normalize - функция нормализует url
from flask import Flask, render_template, redirect, request, abort, flash
import re, os, random, string
import yaml, sys
import yaml, sys, redis
from werkzeug.urls import url_fix
from urllib.parse import urlparse, urlunparse, quote
......@@ -54,7 +55,7 @@ def extract_data_from_yml(urls) -> dict:
:param urls:
:return dict:
"""
# r = redis.Redis('localhost')
r = redis.Redis()
final_dict = {} # словарь с данными из файла .yml
with open(urls, 'r') as stream:
......@@ -63,8 +64,7 @@ def extract_data_from_yml(urls) -> dict:
except yaml.YAMLError as exc: # обработка исключения
print(exc)
# r.hmset("pythonDict", final_dict)
# r.hgetall("pythonDict")
r.mset(final_dict) # загрузить в redis
return final_dict # возвращения словаря
......@@ -109,4 +109,3 @@ def normalize(url: str) -> str:
if __name__ == '__main__':
app.run()
Copyright (c) 2017-2020 Ingy döt Net
Copyright (c) 2006-2016 Kirill Simonov
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.
Metadata-Version: 2.1
Name: PyYAML
Version: 5.3.1
Summary: YAML parser and emitter for Python
Home-page: https://github.com/yaml/pyyaml
Author: Kirill Simonov
Author-email: xi@resolvent.net
License: MIT
Download-URL: https://pypi.org/project/PyYAML/
Platform: Any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Cython
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Markup
YAML is a data serialization format designed for human readability
and interaction with scripting languages. PyYAML is a YAML parser
and emitter for Python.
PyYAML features a complete YAML 1.1 parser, Unicode support, pickle
support, capable extension API, and sensible error messages. PyYAML
supports standard YAML tags and provides Python-specific tags that
allow to represent an arbitrary Python object.
PyYAML is applicable for a broad range of tasks from complex
configuration files to object serialization and persistence.
_yaml.cp37-win_amd64.pyd,sha256=0jKyrtR0-TsVJO2qWlsKdCzsGzn9K29P1Gd1OOIjEwI,275456
yaml/__init__.py,sha256=XFUNbKTg4afAd0BETjGQ1mKQ97_g5jbE1C0WoKc74dc,13170
yaml/composer.py,sha256=_Ko30Wr6eDWUeUpauUGT3Lcg9QPBnOPVlTnIMRGJ9FM,4883
yaml/constructor.py,sha256=O3Uaf0_J_5GQBoeI9ZNhpJAhtdagr_X2HzDgGbZOMnw,28627
yaml/cyaml.py,sha256=LiMkvchNonfoy1F6ec9L2BiUz3r0bwF4hympASJX1Ic,3846
yaml/dumper.py,sha256=PLctZlYwZLp7XmeUdwRuv4nYOZ2UBnDIUy8-lKfLF-o,2837
yaml/emitter.py,sha256=jghtaU7eFwg31bG0B7RZea_29Adi9CKmXq_QjgQpCkQ,43006
yaml/error.py,sha256=Ah9z-toHJUbE9j-M8YpxgSRM5CgLCcwVzJgLLRF2Fxo,2533
yaml/events.py,sha256=50_TksgQiE4up-lKo_V-nBy-tAIxkIPQxY5qDhKCeHw,2445
yaml/loader.py,sha256=UVa-zIqmkFSCIYq_PgSGm4NSJttHY2Rf_zQ4_b1fHN0,2061
yaml/nodes.py,sha256=gPKNj8pKCdh2d4gr3gIYINnPOaOxGhJAUiYhGRnPE84,1440
yaml/parser.py,sha256=ilWp5vvgoHFGzvOZDItFoGjD6D42nhlZrZyjAwa0oJo,25495
yaml/reader.py,sha256=0dmzirOiDG4Xo41RnuQS7K9rkY3xjHiVasfDMNTqCNw,6794
yaml/representer.py,sha256=82UM3ZxUQKqsKAF4ltWOxCS6jGPIFtXpGs7mvqyv4Xs,14184
yaml/resolver.py,sha256=DJCjpQr8YQCEYYjKEYqTl0GrsZil2H4aFOI9b0Oe-U4,8970
yaml/scanner.py,sha256=KeQIKGNlSyPE8QDwionHxy9CgbqE5teJEz05FR9-nAg,51277
yaml/serializer.py,sha256=ChuFgmhU01hj4xgI8GaKv6vfM2Bujwa9i7d2FAHj7cA,4165
yaml/tokens.py,sha256=lTQIzSVw8Mg9wv459-TjiOQe6wVziqaRlqX2_89rp54,2573
yaml/__pycache__/__init__.cpython-37.pyc,sha256=qs7wQyMWYIfISYUK8_uZvraieRKMvlspPUXzFKz15pU,11727
yaml/__pycache__/composer.cpython-37.pyc,sha256=bSIB1bgmsdc98mYcqXVAssZ7O5ZHDnjkEVI8xGUGz-w,3488
yaml/__pycache__/constructor.cpython-37.pyc,sha256=1E7qHez4d4AzJWqGcIcXFdlwPMrBo1PueUsoSg8Xivc,21214
yaml/__pycache__/cyaml.cpython-37.pyc,sha256=7Crqf3ntj_-FLvbRcDIuqfFuH0m09zYsGtOcSiQgbEM,3653
yaml/__pycache__/dumper.cpython-37.pyc,sha256=qhWAfQyp9-CUYEYZuqS2mEyX5V0aPW7WRysXD0mByGY,2028
yaml/__pycache__/emitter.cpython-37.pyc,sha256=oC9FmWRNg048W7LGOUek-mlJki380mCrC8mctsa3t-I,25278
yaml/__pycache__/error.cpython-37.pyc,sha256=UYxA71S4or6Hbu9eV4vkh2ZZoEg4cGACbhrUkx8n82o,2239
yaml/__pycache__/events.cpython-37.pyc,sha256=wX3TDDyYtINJ3-Ut86r76V4Y3tOgB2piVNwj9eL6MOg,4005
yaml/__pycache__/loader.cpython-37.pyc,sha256=p5uhQVBibpNRvuL4ptM_I49UfXJv0MTP5giWxOjNTZ0,2237
yaml/__pycache__/nodes.cpython-37.pyc,sha256=rnW-z93BNZRhYEcxnci1Mk63Gs9zHbGIZgE5UqfTFFM,1683
yaml/__pycache__/parser.cpython-37.pyc,sha256=Z-QZADPiJOh7rMu9IwlNUR7taqCmRXFQVs9bvhCC0XQ,11833
yaml/__pycache__/reader.cpython-37.pyc,sha256=mvbWYrVSL9DRaUTVkLwHyXZekCt9dlt2xOL_A0oQdoY,4446
yaml/__pycache__/representer.cpython-37.pyc,sha256=9wnKR7ZtGG3vLXhtDqFqcXdWy6csWARtpm3ASeQNehE,10069
yaml/__pycache__/resolver.cpython-37.pyc,sha256=CQdNPXYFa5Rsaj9F8t_Pvrml_9kYx_JR8Y4lo6fc6ls,5419
yaml/__pycache__/scanner.cpython-37.pyc,sha256=538Q96NNmyw4BMg2JUZeBlXYA9_ps3ukohiUuwjJsVA,25779
yaml/__pycache__/serializer.cpython-37.pyc,sha256=CnDgLV1hRR2K32VCtiM3EQSkzTXdSMl_u_2n51s0mto,3318
yaml/__pycache__/tokens.cpython-37.pyc,sha256=HSjXc8Jy3q9ytidSHAGcd8HQMlpEggu8qYfgb15hIFQ,5182
PyYAML-5.3.1.dist-info/LICENSE,sha256=xAESRJ8lS5dTBFklJIMT6ScO-jbSJrItgtTMbEPFfyk,1101
PyYAML-5.3.1.dist-info/METADATA,sha256=JMHGIwZThSlNcmGxXTVZ-NFNK3KiEHBdfryJFfPG7Yk,1690
PyYAML-5.3.1.dist-info/WHEEL,sha256=g8eocn77V_iXxq9laUIPSuxdwRHlhOsH3tLpu1uKUvQ,106
PyYAML-5.3.1.dist-info/RECORD,,
PyYAML-5.3.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Wheel-Version: 1.0
Generator: bdist_wheel (0.34.2)
Root-Is-Purelib: false
Tag: cp37-cp37m-win_amd64
Copyright (c) 2012 Andy McCurdy
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.
This diff is collapsed.
redis/__init__.py,sha256=xHeEs2e5uiAwaV0oxJ_DgdOVr8U8Y5OlSCJ9rRbiLkE,1209
redis/_compat.py,sha256=opM78DdCy4D86p9cpN_O81yNgjVDUwOJGLtMS4LL9-0,5698
redis/client.py,sha256=hs1gxHDN9AcpPy1Cpf6yHq4ICtDYofW9XijXpSDeSG0,159611
redis/connection.py,sha256=B5n2unyz5YhSzhsyK9Wa_AXZjT6guxnqHdZcfbe3jqs,55954
redis/exceptions.py,sha256=phjjyJjnebrM82XDzfjtreGnkWIoSNfDZiyoWs3_zQE,1341
redis/lock.py,sha256=VNfWNN46FBwhcPUnFmzC8N8uLuxCsu2YT2drkEzM6_U,11349
redis/sentinel.py,sha256=EhyjT_tZMWKtwuUMMAIRKwfEPL1qBfoldLFQ8tAN1Dg,11710
redis/utils.py,sha256=wG1Ws79_HgIzAALwYwK4CrVLLloVTRPRqjo1gxF4U7U,674
redis-3.5.3.dist-info/LICENSE,sha256=eQFI2MEvijiycHp0viNDMWutEmmV_1SAGhgbiyMboSQ,1074
redis-3.5.3.dist-info/METADATA,sha256=55ufgygbtE8nqMl0UVKD90EZ01zKyemMdxFFOwpubC4,36674
redis-3.5.3.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110
redis-3.5.3.dist-info/top_level.txt,sha256=OMAefszlde6ZoOtlM35AWzpRIrwtcqAMHGlRit-w2-4,6
redis-3.5.3.dist-info/RECORD,,
redis-3.5.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
redis/__pycache__/client.cpython-37.pyc,,
redis/__pycache__/connection.cpython-37.pyc,,
redis/__pycache__/exceptions.cpython-37.pyc,,
redis/__pycache__/lock.cpython-37.pyc,,
redis/__pycache__/sentinel.cpython-37.pyc,,
redis/__pycache__/utils.cpython-37.pyc,,
redis/__pycache__/_compat.cpython-37.pyc,,
redis/__pycache__/__init__.cpython-37.pyc,,
Wheel-Version: 1.0
Generator: bdist_wheel (0.34.2)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any
from redis.client import Redis, StrictRedis
from redis.connection import (
BlockingConnectionPool,
ConnectionPool,
Connection,
SSLConnection,
UnixDomainSocketConnection
)
from redis.utils import from_url
from redis.exceptions import (
AuthenticationError,
AuthenticationWrongNumberOfArgsError,
BusyLoadingError,
ChildDeadlockedError,
ConnectionError,
DataError,
InvalidResponse,
PubSubError,
ReadOnlyError,
RedisError,
ResponseError,
TimeoutError,
WatchError
)
def int_or_str(value):
try:
return int(value)
except ValueError:
return value
__version__ = '3.5.3'
VERSION = tuple(map(int_or_str, __version__.split('.')))
__all__ = [
'AuthenticationError',
'AuthenticationWrongNumberOfArgsError',
'BlockingConnectionPool',
'BusyLoadingError',
'ChildDeadlockedError',
'Connection',
'ConnectionError',
'ConnectionPool',
'DataError',
'from_url',
'InvalidResponse',
'PubSubError',
'ReadOnlyError',
'Redis',
'RedisError',
'ResponseError',
'SSLConnection',
'StrictRedis',
'TimeoutError',
'UnixDomainSocketConnection',
'WatchError',
]
"""Internal module for Python 2 backwards compatibility."""
# flake8: noqa
import errno
import socket
import sys
def sendall(sock, *args, **kwargs):
return sock.sendall(*args, **kwargs)
def shutdown(sock, *args, **kwargs):
return sock.shutdown(*args, **kwargs)
def ssl_wrap_socket(context, sock, *args, **kwargs):
return context.wrap_socket(sock, *args, **kwargs)
# For Python older than 3.5, retry EINTR.
if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and
sys.version_info[1] < 5):
# Adapted from https://bugs.python.org/review/23863/patch/14532/54418
import time
# Wrapper for handling interruptable system calls.
def _retryable_call(s, func, *args, **kwargs):
# Some modules (SSL) use the _fileobject wrapper directly and
# implement a smaller portion of the socket interface, thus we
# need to let them continue to do so.
timeout, deadline = None, 0.0
attempted = False
try:
timeout = s.gettimeout()
except AttributeError:
pass
if timeout:
deadline = time.time() + timeout
try:
while True:
if attempted and timeout:
now = time.time()
if now >= deadline:
raise socket.error(errno.EWOULDBLOCK, "timed out")
else:
# Overwrite the timeout on the socket object
# to take into account elapsed time.
s.settimeout(deadline - now)
try:
attempted = True
return func(*args, **kwargs)
except socket.error as e:
if e.args[0] == errno.EINTR:
continue
raise
finally:
# Set the existing timeout back for future
# calls.
if timeout:
s.settimeout(timeout)
def recv(sock, *args, **kwargs):
return _retryable_call(sock, sock.recv, *args, **kwargs)
def recv_into(sock, *args, **kwargs):
return _retryable_call(sock, sock.recv_into, *args, **kwargs)
else: # Python 3.5 and above automatically retry EINTR
def recv(sock, *args, **kwargs):
return sock.recv(*args, **kwargs)
def recv_into(sock, *args, **kwargs):
return sock.recv_into(*args, **kwargs)
if sys.version_info[0] < 3:
# In Python 3, the ssl module raises socket.timeout whereas it raises
# SSLError in Python 2. For compatibility between versions, ensure
# socket.timeout is raised for both.
import functools
try:
from ssl import SSLError as _SSLError
except ImportError:
class _SSLError(Exception):
"""A replacement in case ssl.SSLError is not available."""
pass
_EXPECTED_SSL_TIMEOUT_MESSAGES = (
"The handshake operation timed out",
"The read operation timed out",
"The write operation timed out",
)
def _handle_ssl_timeout(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except _SSLError as e:
message = len(e.args) == 1 and unicode(e.args[0]) or ''
if any(x in message for x in _EXPECTED_SSL_TIMEOUT_MESSAGES):
# Raise socket.timeout for compatibility with Python 3.
raise socket.timeout(*e.args)
raise
return wrapper
recv = _handle_ssl_timeout(recv)
recv_into = _handle_ssl_timeout(recv_into)
sendall = _handle_ssl_timeout(sendall)
shutdown = _handle_ssl_timeout(shutdown)
ssl_wrap_socket = _handle_ssl_timeout(ssl_wrap_socket)
if sys.version_info[0] < 3:
from urllib import unquote
from urlparse import parse_qs, urlparse
from itertools import imap, izip
from string import letters as ascii_letters
from Queue import Queue
# special unicode handling for python2 to avoid UnicodeDecodeError
def safe_unicode(obj, *args):
""" return the unicode representation of obj """
try:
return unicode(obj, *args)
except UnicodeDecodeError:
# obj is byte string
ascii_text = str(obj).encode('string_escape')
return unicode(ascii_text)
def iteritems(x):
return x.iteritems()
def iterkeys(x):
return x.iterkeys()
def itervalues(x):
return x.itervalues()
def nativestr(x):
return x if isinstance(x, str) else x.encode('utf-8', 'replace')
def next(x):
return x.next()
unichr = unichr
xrange = xrange
basestring = basestring
unicode = unicode
long = long
BlockingIOError = socket.error
else:
from urllib.parse import parse_qs, unquote, urlparse
from string import ascii_letters
from queue import Queue
def iteritems(x):
return iter(x.items())
def iterkeys(x):
return iter(x.keys())
def itervalues(x):
return iter(x.values())
def nativestr(x):
return x if isinstance(x, str) else x.decode('utf-8', 'replace')
def safe_unicode(value):
if isinstance(value, bytes):
value = value.decode('utf-8', 'replace')
return str(value)
next = next
unichr = chr
imap = map
izip = zip
xrange = range
basestring = str
unicode = str
long = int
BlockingIOError = BlockingIOError
try: # Python 3
from queue import LifoQueue, Empty, Full
except ImportError: # Python 2
from Queue import LifoQueue, Empty, Full
This diff is collapsed.
This diff is collapsed.
"Core exceptions raised by the Redis client"
class RedisError(Exception):
pass
class ConnectionError(RedisError):
pass
class TimeoutError(RedisError):
pass
class AuthenticationError(ConnectionError):
pass
class BusyLoadingError(ConnectionError):
pass
class InvalidResponse(RedisError):
pass
class ResponseError(RedisError):
pass
class DataError(RedisError):
pass
class PubSubError(RedisError):
pass
class WatchError(RedisError):
pass
class NoScriptError(ResponseError):
pass
class ExecAbortError(ResponseError):
pass
class ReadOnlyError(ResponseError):
pass
class NoPermissionError(ResponseError):
pass
class LockError(RedisError, ValueError):
"Errors acquiring or releasing a lock"
# NOTE: For backwards compatability, this class derives from ValueError.
# This was originally chosen to behave like threading.Lock.
pass
class LockNotOwnedError(LockError):
"Error trying to extend or release a lock that is (no longer) owned"
pass
class ChildDeadlockedError(Exception):
"Error indicating that a child process is deadlocked after a fork()"
pass
class AuthenticationWrongNumberOfArgsError(ResponseError):
"""
An error to indicate that the wrong number of args
were sent to the AUTH command
"""
pass
import threading
import time as mod_time
import uuid
from redis.exceptions import LockError, LockNotOwnedError
from redis.utils import dummy
class Lock(object):
"""
A shared, distributed Lock. Using Redis for locking allows the Lock
to be shared across processes and/or machines.
It's left to the user to resolve deadlock issues and make sure
multiple clients play nicely together.
"""
lua_release = None
lua_extend = None
lua_reacquire = None
# KEYS[1] - lock name
# ARGV[1] - token
# return 1 if the lock was released, otherwise 0
LUA_RELEASE_SCRIPT = """
local token = redis.call('get', KEYS[1])
if not token or token ~= ARGV[1] then
return 0
end
redis.call('del', KEYS[1])
return 1
"""
# KEYS[1] - lock name
# ARGV[1] - token
# ARGV[2] - additional milliseconds
# ARGV[3] - "0" if the additional time should be added to the lock's
# existing ttl or "1" if the existing ttl should be replaced
# return 1 if the locks time was extended, otherwise 0