{ "info": { "author": "EBS Integrator", "author_email": "office@ebs-integrator.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Django", "Framework :: Django :: 1.11", "Framework :: Django :: 2.0", "Framework :: Django :: 2.1", "Framework :: Django :: 2.2", "Framework :: Django :: 3.0", "Framework :: Django :: 3.1", "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Utilities" ], "description": "# Django Rest Framework - Utils\n\nA set of util functions used in EBS Projects\n\n### Install:\n\n```bash\npip install drf_util\n```\n\n### Functions\n\n#### Get value from an object by path\n\nDefinition:\n\n```python\ngt(obj, path, default=None, sep='.')\n```\n\nUsage:\n\n```python\n>>> data = {\"a\":{\"b\": 1}}\n>>> print(gt(data, 'a.b'))\n1\n```\n\n#### Get recursive values from a dict by keys\n\nDefinition:\n\n```python\nget_object_labels(obj, path, default=None)\n```\n\nUsage:\n\n```python\n>>> data = {\"a\": {\"b\": 'title'}, \"c\": 'test'}\n>>> print(get_object_labels(data))\n['title', 'test']\n\n>>> data = {\"a\": {\"b\": 'title'}, \"c\": 'test'}\n>>> print(get_object_labels(data, ['c']))\n['test']\n```\n\n#### map() alternative with chunk select\n\nDefinition:\n\n```python\nfetch_objects(instance, function, select=50)\n```\n\nUsage:\n\n```python\n>>> def print_name(obj):\n print obj.name\n>>>\n>>> fetch_objects(UserBigList.objects.order_by('id'), print_name, 500)\n```\n\n#### Select a first true value\n\nDefinition:\n\n```python\nany_value(items: list)\n```\n\nUsage:\n\n```python\n>>> print(any_value('', None, 0, \"Some text\", 50000))\nSome text\n```\n\n#### Recursive merge two dict\n\nDefinition:\n\n```python\ndict_merge(a, b, path=None)\n```\n\nUsage:\n\n```python\n>>> a = {'a': {'c': 1, 'd': {'x': 1}}}\n>>> b = {'a': {'e': 1, 'd': {'y': 1}}}\n>>> print(dict_merge(a, b))\n{'a': {'c': 1, 'e': 1, 'd': {'x': 1, 'y': 1}}}\n```\n\n#### Iterate big query\n\nDefinition:\n\n```python\niterate_query(queryset, offset_field, offset_start, limit=100)\n```\n\nUsage:\n\n```python\nqueryset = Thing.objects.all()\nfor _ in utils.iterate_query(queryset, 'id', 0):\n ...\n```\n\n#### Get applications from folder\n\nDefinition:\n\n```python\nget_applications(base_folder='apps', inside_file='', only_directory=True)\n```\n\nUsage:\n\n```python\n# settings.py\nAPPS_PATH = 'path_to_aps' # default is apps\n...\n\n# any file\nget_applications() # ['path_to_aps.app1', 'path_to_aps.app2']\nget_applications(inside_file='models.py',\n only_directory=False) # ['path_to_aps.app1.models', 'path_to_aps.app2.models']\n```\n\nTricks:\n\n```python\n# settings.py\nINSTALLED_APPS = get_applications()\n...\n\n# urls.py\nurlpatterns = [\n path(\"\", include(application_urls))\n \n for application_urls in get_applications(\n inside_file='urls.py', only_directory=False\n ))\n]\n```\n\n#### Prefetch and select related by serializer \nDefinition:\n```python\nadd_related(queryset, serializer)\n```\n\nUsage:\n```python\nqueryset = add_related(Thing.objects.all(), ThingSerializer)\n```\n\n### Decorators\n\n##### serialize_decorator\n\nDefinition:\n\n```python\nserialize_decorator(serializer_method, preview_function=None, read_params=False)\n```\n\nUsage:\n\n```python\nclass RestoreUserPassword(GenericAPIView):\n @serialize_decorator(RestoreUserSerializer)\n def post(self, request, *args, **kwargs):\n return Response({\"valid\": True})\n```\n\n##### await_process_decorator\n\nDecorator for creating a queue for using a function, it is needed to adjust the call of a function from different\nprocesses (\u0421elery, Threads). For example, this decorator can be used to limit the number of requests in the parser.\n\nDefinition:\n\n```python\n# rate : count of usage some function, by default it's 20 times\n# period : period of usage some function, by default it's 1 minute\nawait_process_decorator(rate=20, period=60)\n```\n\nUsage:\n\n```python\n@await_process_decorator(rate=10, period=5) # 10 times per 5 seconds \ndef simple_print(text):\n print(text)\n```\n\n### Managers\n\n- NoDeleteManager\n\n### Models\n\n#### BaseModel - with created_at and updated_at\n\n```python\nclass Thing(BaseModel):\n title = models.CharField(max_length=20)\n\n class Meta:\n db_table = 'another_things'\n```\n\n- CommonModel - with date_created and date_updated\n- NoDeleteModel - with date_deleted\n- AbstractJsonModel - with languages\n\n### Validators\n\n- ObjectExistValidator - check if object exists\n- ObjectUniqueValidator - check if object not exists\n- PhoneValidator - check phone\n\n### Serializers\n\n#### BaseModelSerializer - simple serializer for BaseModel class\n\n```python\nclass ThingSerializer(BaseModelSerializer):\n class Meta(BaseModelSerializer.Meta):\n model = Thing\n```\n\n#### ElasticFilterSerializer - make easy conversion between serializer data and elastic filters\n\n```python\nclass TenderFilterSerializer(PaginatorSerializer, ElasticFilterSerializer):\n sort_criteria = [{\"date_updated\": {\"order\": \"desc\"}}, \"_score\"]\n\n status = StringListField(required=False)\n date_start = serializers.DateField(required=False)\n date_end = serializers.DateField(required=False)\n\n def filter_status(self, value):\n return {'terms': {\n 'search_status.keyword': value\n }}\n\n def filter_date_start(self, value):\n return {\n \"range\": {\n \"tenderPeriod.startDate\": {'gte': value}\n }\n }\n\n def filter_date_end(self, value):\n return {\n \"range\": {\n \"tenderPeriod.startDate\": {'lte': value}\n }\n }\n\n\nclass TenderListView(GenericAPIView):\n @serialize_decorator(TenderFilterSerializer)\n def get(self, request, *args, **kwargs):\n return Response(es_app.search_response(request.serializer, 'tenders_index'))\n```\n\n#### FilterSerializer - filter queryset by serializer fields\n\n```python\nclass ServiceListQuerySerializer(FilterSerializer):\n name = CharField(required=False)\n tag_id = CharField(required=False)\n type = CharField(required=False)\n status = CharField(required=False)\n\n def filter_name(self, value, queryset):\n return queryset.filter(name__icontains=value)\n\n def filter_tag_id(self, value, queryset):\n return queryset.filter(tags__contains=value)\n\n def filter_type(self, value, queryset):\n return queryset.filter(type=value)\n\n def filter_status(self, value, queryset):\n return queryset.filter(status=value)\n\n\nclass ServiceListView(ListAPIView):\n serializer_class = ServiceListQuerySerializer\n\n @swagger_auto_schema(query_serializer=ServiceListQuerySerializer)\n @serialize_decorator(ServiceListQuerySerializer)\n def get(self, request):\n services = request.serializer.get_filter(request.valid, Service.objects.all())\n return Response(ServiceSerializer(instance=services, many=True).data)\n```\n\n#### ChangebleSerializer - metamorphic serializer\n\n```python\nclass ContractNoticeCancelView(GenericAPIView):\n def put(self, request):\n serializer_meta = {\n 'id': PrimaryKeyRelatedField(queryset=Tender.objects.all(), required=True),\n 'info': {\n 'rationale': CharField(required=True),\n 'description': CharField(required=True),\n },\n 'documents': DocumentFileSerializer(required=True, many=True)\n }\n serializer = ChangebleSerializer(data=request.data)\n serializer.update_properties(serializer_meta)\n serializer.is_valid(raise_exception=True)\n\n return Response({\"valid\": True})\n```\n\n#### PaginatorSerializer - serializer for paginating\n\n```python\nclass ListUserNotification(GenericAPIView):\n @serialize_decorator(PaginatorSerializer)\n def get(self, request):\n notifications = NotificationEvent.objects.filter(user=request.user)\n return request.serializer.response(notifications, serializer=ListNotificationSerializer)\n```\n\n#### Another serializers\n\n- StringListField - simple string list of chars\n- EmptySerializer - simple empty serializer\n- IdSerializer - simple id serializer\n- ReturnSuccessSerializer - simple success, message serializer\n\n### Serializers functions\n\n#### build_model_serializer - build serializer with Inheritance\n\nDefinition:\n```python\nbuild_model_serializer(base=BaseModelSerializer, add_bases=True, **kwargs)\n```\n\nUsage:\n```python\nThingSerializer = build_model_serializer(\n meta_model=Thing,\n)\n\nCreateThingSerializer = build_model_serializer(\n ThingSerializer,\n meta_fields=('name', 'desctiption')\n)\n\nCreateThingSerializer = build_model_serializer(\n ThingSerializer,\n meta_fields=('name', 'desctiption') # 'id', 'created_at' and 'updated_at' is added automatically\n)\n\nShortThingSerializer = build_model_serializer(\n ThingSerializer,\n meta_fields=('name', 'desctiption'),\n add_bases=False # so as not to add 'id', 'created_at' and 'updated_at'\n)\n\n\nAnotherThingSerializer = build_model_serializer(\n things=ThingSerializer(many=True),\n meta_model=AnotherThing,\n)\n```\n\n\n---\n**Note:**\nParameters with prefix 'meta_' is added to the meta class, the rest are added in the serializer class \n---\n\n\n\n### Views\n\nNote: for them to work, set in swagger settings \nDEFAULT_AUTO_SCHEMA_CLASS=drf_util.mixins.CustomAutoSchema\n\n#### BaseModelViewSet\n\nUsage:\n```python\nclass ThingViewSet(BaseModelViewSet):\n queryset = Thing.objects.all()\n serializer_class = ThingSerializer\n```\n\nAttributes:\n\n```python\nqueryset = None # QuerySet\n\nquery_serializer = None # Serializer for query\nserializer_class = None # Default and response serializer\nserializer_create_class = None # Body serializer\nserializer_by_action = {} # Serializer by action {[action]: [serializer]}\n\npagination_class = CustomPagination # Pagination\n\nfilter_backends = (filters.OrderingFilter, CustomFilterBackend, filters.SearchFilter,) # Filter backends\nfilter_class = None # FilterSet\nsearch_fields = () # Fields for search query_param\nordering_fields = '__all__' # Fields for ordering query_param\nordering = ['-id'] # Default ordering fields\n\npermission_classes_by_action = {\"default\": [IsAuthenticated]} # Permission class by action {[action]: [permissions]}\n```\n\n#### Another views\n\n- BaseViewSet\n- BaseCreateModelMixin\n- BaseUpdateModelMixin\n- BaseListModelMixin\n- BaseReadOnlyViewSet\n- BaseModelItemViewSet\n- BaseModelViewSet\n\n\n### Pagination\n\n#### CustomPagination\n\nDeclaration:\n\n```python\nclass CustomPagination(PageNumberPagination):\n page = DEFAULT_PAGE\n page_size = 10\n page_size_query_param = 'per_page'\n\n def get_paginated_response(self, data):\n custom_paginator = dict(\n count=self.page.paginator.count, # noqa\n total_pages=self.page.paginator.num_pages, # noqa\n per_page=int(self.request.GET.get('per_page', self.page_size)),\n current_page=int(self.request.GET.get('page', DEFAULT_PAGE)), results=data\n )\n return Response(custom_paginator)\n```\n\n### Tests\n\n#### CustomClient - client which check response for status code\n\nUsage:\n```python\nclass BaseTestCase(TestCase):\n client_class = CustomClient\n base_view = 'things'\n \n def test_list(self) -> None:\n self.client.get(reverse(f'{self.base_view}-list'))\n \n def test_duplicate(self):\n self.client.post(\n reverse(f'{self.base_view}-duplicate', args=(test_instance.pk,)),\n assert_status_code=status.HTTP_200_OK\n ).json()\n```\n\n#### BaseTestCase - test case with custom client\n\nUsage:\n\n```python\nclass ViewsTestCase(BaseTestCase, TestCase):\n def test_swagger(self):\n response = self.client.get('/swagger/?format=openapi').json()\n self.assertEqual(len(response['schemes']), 2)\n```\n\n---\n**Note:**\nDefault setUp function authenticates the user\n---\n\n#### CRUDTestCase - test case with crud\n\nUsage:\n\n```python\nclass ThingCRUDTestCase(CRUDTestCase, TestCase):\n fixtures = ['tests/fixtures.json']\n base_view = 'things'\n queryset = Thing.objects.all()\n fake_data = {\n 'title': 'Thing name'\n }\n```\n\n\n### Middlewares\n#### PrintSQlMiddleware - middleware to print sql request and their statistics\n\nUsage:\n\n```python\nMIDDLEWARE = [\n 'drf_util.middlewares.PrintSQlMiddleware',\n ...\n]\n```\n\n### Swagger utils\n#### CustomAutoSchema - render schema with custom serializers methods\n\nUsage:\n\n```python\nSWAGGER_SETTINGS = {\n 'DEFAULT_AUTO_SCHEMA_CLASS': 'drf_util.mixins.CustomAutoSchema'\n ...\n}\n```\n\n#### get_custom_schema_view - function to get swagger with HTTP and HTTPS\n\nDeclaration:\n\n```python\nget_custom_schema_view(title, default_version='v1', description='', *args, **kwargs)\n```\n\nUsage:\n\n```python\nschema_view = get_custom_schema_view(\n title=\"API Documentation\",\n description=\"This is API Documentation\"\n)\n\nurlpatterns = [\n path(\"\", schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),\n path(\"redoc\", schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'), \n]\n```\n\n\n\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/EnterpriseBusinessSolutions/drf-util", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "drf-util", "package_url": "https://pypi.org/project/drf-util/", "platform": "", "project_url": "https://pypi.org/project/drf-util/", "project_urls": { "Homepage": "https://github.com/EnterpriseBusinessSolutions/drf-util" }, "release_url": "https://pypi.org/project/drf-util/1.0.14/", "requires_dist": null, "requires_python": ">=3.4", "summary": "Django Rest Framework Utils", "version": "1.0.14", "yanked": false, "yanked_reason": null }, "last_serial": 12838319, "releases": { "0.0.10": [ { "comment_text": "", "digests": { "md5": "58a03a826a15781a1aac1847b4391512", "sha256": "e9974cf672cda13406730d1d407baf22cc094b3b68bfae2d69a7d09fff0e4458" }, "downloads": -1, "filename": "drf_util-0.0.10.tar.gz", "has_sig": false, "md5_digest": "58a03a826a15781a1aac1847b4391512", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 8170, "upload_time": "2019-03-28T12:15:11", "upload_time_iso_8601": "2019-03-28T12:15:11.141183Z", "url": "https://files.pythonhosted.org/packages/ff/ef/25ec45b9f31080f4a297a7bf62907a8e690fe73b7b296168db4e6676bd20/drf_util-0.0.10.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.11": [ { "comment_text": "", "digests": { "md5": "4fb229674142c125acadb7ca7a43ad12", "sha256": "f91bb3b428d2c41aacee914c35dc21541bf1523edddca9c8fbf38ee28f346de8" }, "downloads": -1, "filename": "drf_util-0.0.11.tar.gz", "has_sig": false, "md5_digest": "4fb229674142c125acadb7ca7a43ad12", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 8181, "upload_time": "2019-04-15T09:35:10", "upload_time_iso_8601": "2019-04-15T09:35:10.312989Z", "url": "https://files.pythonhosted.org/packages/f8/45/8d657d72200229a5105b668102467552eede8cc5ff451fab8b22a4939a87/drf_util-0.0.11.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.12": [ { "comment_text": "", "digests": { "md5": "5f1240560688a3ba9004063c1915f5a3", "sha256": "14832d9a9ba97e351bec4d15ce52203d666807a60337d8594ae992c8c468c9d1" }, "downloads": -1, "filename": "drf_util-0.0.12.tar.gz", "has_sig": false, "md5_digest": "5f1240560688a3ba9004063c1915f5a3", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 8191, "upload_time": "2019-05-07T08:39:14", "upload_time_iso_8601": "2019-05-07T08:39:14.370753Z", "url": "https://files.pythonhosted.org/packages/34/7e/88456c2d59c9bd46b85cb25e3b16d0049af126f7e729ff104025d4175e9d/drf_util-0.0.12.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.13": [ { "comment_text": "", "digests": { "md5": "9bca0ca18d61d5ca953e65c57e93a665", "sha256": "479fd1eff965c52512d05e9708653abc00ce81b8d5d859411744835873648e0f" }, "downloads": -1, "filename": "drf_util-0.0.13.tar.gz", "has_sig": false, "md5_digest": "9bca0ca18d61d5ca953e65c57e93a665", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 8208, "upload_time": "2019-08-02T14:34:16", "upload_time_iso_8601": "2019-08-02T14:34:16.170837Z", "url": "https://files.pythonhosted.org/packages/4e/7a/b18543eb05d6ca03bc0c868ea1666b3a2b74a0b5541b6170a9018a9620b7/drf_util-0.0.13.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.14": [ { "comment_text": "", "digests": { "md5": "049560628e56ea7a9b2dcd121cc2c5f1", "sha256": "15a3423f09b5a3a332b7c4aa218d9b08a7b105e30a0d9c27fb0b0bad7aff334b" }, "downloads": -1, "filename": "drf_util-0.0.14.tar.gz", "has_sig": false, "md5_digest": "049560628e56ea7a9b2dcd121cc2c5f1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 8618, "upload_time": "2019-08-03T09:36:15", "upload_time_iso_8601": "2019-08-03T09:36:15.243337Z", "url": "https://files.pythonhosted.org/packages/b4/96/6e107c0c0d833a856fce9dfd577f0663b7f7a95fcf1784cc7ec496c8602b/drf_util-0.0.14.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.15": [ { "comment_text": "", "digests": { "md5": "1d7e7c7b21ce28333a5815bbc028f8b6", "sha256": "4d744d857f38217171b541982a4105091505aa72085a246c7b9e54662cc4a56e" }, "downloads": -1, "filename": "drf_util-0.0.15.tar.gz", "has_sig": false, "md5_digest": "1d7e7c7b21ce28333a5815bbc028f8b6", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 8626, "upload_time": "2019-09-03T08:42:34", "upload_time_iso_8601": "2019-09-03T08:42:34.226366Z", "url": "https://files.pythonhosted.org/packages/32/40/7feded87564097fe0bcd5884ebd8e55ead271af0c32f740d132e89efa4ac/drf_util-0.0.15.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.16": [ { "comment_text": "", "digests": { "md5": "33cdf6b92411045e3b697a87961448c0", "sha256": "17c18ac6da0b67723b91d09ff5acf2c1c8f1fb46c9bab5e3a40e9033c1848d00" }, "downloads": -1, "filename": "drf_util-0.0.16.tar.gz", "has_sig": false, "md5_digest": "33cdf6b92411045e3b697a87961448c0", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 10074, "upload_time": "2019-09-26T15:22:04", "upload_time_iso_8601": "2019-09-26T15:22:04.040457Z", "url": "https://files.pythonhosted.org/packages/68/f0/7a911ac8251964a732ae0f009e88bd41f8197f2280f611b45dcaca6c953f/drf_util-0.0.16.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.17": [ { "comment_text": "", "digests": { "md5": "5b6ab4e46a528fa29892385e80868310", "sha256": "55a2c5ae2d7eb88e70577d8c9542309e0c6b474def464730984d40dbf35304b8" }, "downloads": -1, "filename": "drf_util-0.0.17.tar.gz", "has_sig": false, "md5_digest": "5b6ab4e46a528fa29892385e80868310", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 8645, "upload_time": "2019-10-21T08:47:12", "upload_time_iso_8601": "2019-10-21T08:47:12.006998Z", "url": "https://files.pythonhosted.org/packages/65/40/457fcb50797e9334944ca52727f94f277dc2bba6b0e7ac998c0fb31b4c74/drf_util-0.0.17.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.18": [ { "comment_text": "", "digests": { "md5": "6594af9e6ca60511466c5674fb1cf8ad", "sha256": "da2d760b0c7827dce5575f97adfe2bd6c5084f2c73cee8900ecabe78496edd71" }, "downloads": -1, "filename": "drf_util-0.0.18.tar.gz", "has_sig": false, "md5_digest": "6594af9e6ca60511466c5674fb1cf8ad", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 10696, "upload_time": "2019-11-30T13:36:32", "upload_time_iso_8601": "2019-11-30T13:36:32.166933Z", "url": "https://files.pythonhosted.org/packages/4e/4f/429edf5690990de761a9a1df9bf249b6239a8c6c8e32c706fff069c339a2/drf_util-0.0.18.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.19": [ { "comment_text": "", "digests": { "md5": "9dc594bb6f74c82e09ba511b1e0f4ffd", "sha256": "bf2c0e4941479218ba0b0b784c617cdeacc627ce7fb2d7b3fdcbd11998eb5e68" }, "downloads": -1, "filename": "drf_util-0.0.19.tar.gz", "has_sig": false, "md5_digest": "9dc594bb6f74c82e09ba511b1e0f4ffd", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 11916, "upload_time": "2019-12-26T08:53:30", "upload_time_iso_8601": "2019-12-26T08:53:30.272529Z", "url": "https://files.pythonhosted.org/packages/3d/e7/7e234cc4ea9bb7c7c141adc3183fcaa8d3aec177b46e49907874653d8f4a/drf_util-0.0.19.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.20": [ { "comment_text": "", "digests": { "md5": "fd9bd874af26e5774aa12e1b12ed561a", "sha256": "447d2b15ac65d11448d975fced4d8b7e1191a14b400c226cc19229e55ac26ddb" }, "downloads": -1, "filename": "drf_util-0.0.20.tar.gz", "has_sig": false, "md5_digest": "fd9bd874af26e5774aa12e1b12ed561a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 12005, "upload_time": "2019-12-26T15:18:50", "upload_time_iso_8601": "2019-12-26T15:18:50.132892Z", "url": "https://files.pythonhosted.org/packages/00/97/9aaf471aebf9c76ad76f5473d75db5845792711ad2b31513fb6f9b89a31a/drf_util-0.0.20.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.21": [ { "comment_text": "", "digests": { "md5": "e36ea87465c3084924232fde6ee6fbcb", "sha256": "840b08b56a7e13d900767b4df690ec7243896bcf7660ddf0d0524882ae77e943" }, "downloads": -1, "filename": "drf_util-0.0.21.tar.gz", "has_sig": false, "md5_digest": "e36ea87465c3084924232fde6ee6fbcb", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 13480, "upload_time": "2020-01-14T11:54:39", "upload_time_iso_8601": "2020-01-14T11:54:39.089545Z", "url": "https://files.pythonhosted.org/packages/5e/28/73a3ebe5fc6b7942d9dbb852fd7500f7b452a3a4c0583ab250ae52ef3c33/drf_util-0.0.21.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.22": [ { "comment_text": "", "digests": { "md5": "fadb4013f6dc1c1478436ff106179e19", "sha256": "82d664496d2a5d3905b89ea522d4020ca0e33bd041363fd1fe6c9434503555af" }, "downloads": -1, "filename": "drf_util-0.0.22.tar.gz", "has_sig": false, "md5_digest": "fadb4013f6dc1c1478436ff106179e19", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 13481, "upload_time": "2020-01-14T15:36:57", "upload_time_iso_8601": "2020-01-14T15:36:57.673225Z", "url": "https://files.pythonhosted.org/packages/ff/27/1a9f32225ee37d863ed62ca09db8677ccda38d5b3176d19906d7e4ece766/drf_util-0.0.22.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.23": [ { "comment_text": "", "digests": { "md5": "6cf83da7bf863d6004fdb1f9d0a48866", "sha256": "6dbb8306b155f2d435c1c7d18a3be0d05193a444cfbbd35d5d329212b7e6c9d3" }, "downloads": -1, "filename": "drf_util-0.0.23.tar.gz", "has_sig": false, "md5_digest": "6cf83da7bf863d6004fdb1f9d0a48866", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 13499, "upload_time": "2020-01-27T08:55:06", "upload_time_iso_8601": "2020-01-27T08:55:06.519990Z", "url": "https://files.pythonhosted.org/packages/25/8f/19be4f1b224a3f953ddec317864399ce1ad2efe63eb1384cab385d8c2ef5/drf_util-0.0.23.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.24": [ { "comment_text": "", "digests": { "md5": "ae404e168a7af4982aa99dfda61e4c36", "sha256": "172acdc13cc9e8de1b6a9fc4a1219e27763d8227dfea827ecb266ac23f26a22c" }, "downloads": -1, "filename": "drf_util-0.0.24.tar.gz", "has_sig": false, "md5_digest": "ae404e168a7af4982aa99dfda61e4c36", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 13492, "upload_time": "2020-04-02T13:09:45", "upload_time_iso_8601": "2020-04-02T13:09:45.221764Z", "url": "https://files.pythonhosted.org/packages/ba/9b/54bc875ccb978fb1f919da261ddd0f83f0477db10cf793d32141a6f3724e/drf_util-0.0.24.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.25": [ { "comment_text": "", "digests": { "md5": "7fc45f06fd51ae8faf987072474ef61e", "sha256": "f5d8d51fc3ad01bc9ce6e1321eb45f8dccce081829cb20c80c33c7fd2124f452" }, "downloads": -1, "filename": "drf_util-0.0.25.tar.gz", "has_sig": false, "md5_digest": "7fc45f06fd51ae8faf987072474ef61e", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 13507, "upload_time": "2020-05-06T12:09:08", "upload_time_iso_8601": "2020-05-06T12:09:08.122179Z", "url": "https://files.pythonhosted.org/packages/1d/4a/cdfb811070a0798dae2871459474289d470af95950762c410f593080e031/drf_util-0.0.25.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.26": [ { "comment_text": "", "digests": { "md5": "4673b64e689214052f9068730a9adfc5", "sha256": "0f121e4300e55cd58110a27e9daa0be46bdc2d8f0f317009a9d7819a938b42c5" }, "downloads": -1, "filename": "drf_util-0.0.26.tar.gz", "has_sig": false, "md5_digest": "4673b64e689214052f9068730a9adfc5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 13550, "upload_time": "2020-05-13T09:43:36", "upload_time_iso_8601": "2020-05-13T09:43:36.514770Z", "url": "https://files.pythonhosted.org/packages/c3/2c/7b92103414d9e39a316606c54153ab8545822366cc0bb1aa14f741bf5514/drf_util-0.0.26.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.27": [ { "comment_text": "", "digests": { "md5": "dbc7a624a802f9e3fd38eea5f53e3d9f", "sha256": "4402d4765e23fb29cb5a26d08ea3c044cbc8118be5327e546d8952d3e5211fc7" }, "downloads": -1, "filename": "drf_util-0.0.27.tar.gz", "has_sig": false, "md5_digest": "dbc7a624a802f9e3fd38eea5f53e3d9f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 13590, "upload_time": "2020-05-13T15:53:45", "upload_time_iso_8601": "2020-05-13T15:53:45.451756Z", "url": "https://files.pythonhosted.org/packages/4a/87/464453b5aad4adec4e93432813c8c6bf6c4242a19efa2882a27b5882aacd/drf_util-0.0.27.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.28": [ { "comment_text": "", "digests": { "md5": "7929ac3e18883d8fae98521c3234f216", "sha256": "156299bcc3f58df2d000fe9414e780472a91fb347a22639cadb21a71ebc7f32e" }, "downloads": -1, "filename": "drf_util-0.0.28.tar.gz", "has_sig": false, "md5_digest": "7929ac3e18883d8fae98521c3234f216", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 13594, "upload_time": "2020-09-30T13:27:11", "upload_time_iso_8601": "2020-09-30T13:27:11.751303Z", "url": "https://files.pythonhosted.org/packages/f8/57/fda5438a7b3dd6a6da7ae963a83db8597bfd9e59689355efe9a65ff44a71/drf_util-0.0.28.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.29": [ { "comment_text": "", "digests": { "md5": "f2b4888ecbb5201eb4b5fece9e59aa41", "sha256": "cd742fcee2d823f5e7eca9124f29ae571a46bffded593930eb35ac419411f091" }, "downloads": -1, "filename": "drf_util-0.0.29.tar.gz", "has_sig": false, "md5_digest": "f2b4888ecbb5201eb4b5fece9e59aa41", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 13605, "upload_time": "2021-03-24T08:32:44", "upload_time_iso_8601": "2021-03-24T08:32:44.850045Z", "url": "https://files.pythonhosted.org/packages/ab/d8/5e020b859dbc29386bf69c74e3b037ae94c6653a983fc2848a57731d1e56/drf_util-0.0.29.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.7": [ { "comment_text": "", "digests": { "md5": "d59f9391c3463986c7c07978e99012cd", "sha256": "d8d896ad896f469d542d6faa826d668b66860fc9cb387ab3b5ab8ae9f5425175" }, "downloads": -1, "filename": "drf_util-0.0.7.tar.gz", "has_sig": false, "md5_digest": "d59f9391c3463986c7c07978e99012cd", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 7994, "upload_time": "2019-03-26T18:37:34", "upload_time_iso_8601": "2019-03-26T18:37:34.449742Z", "url": "https://files.pythonhosted.org/packages/6b/bd/ed4d5bd72edbf076a1767f516ce02d9dbbaac3d46d1cfa25894cff86136a/drf_util-0.0.7.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.8": [ { "comment_text": "", "digests": { "md5": "3ae1675b9f3e73bfcc6a2ef74ddb3086", "sha256": "65ff685d7116e1d7c61cb7be98f96b3fdedf04893b8aacbf5e180ee0a3f1be0d" }, "downloads": -1, "filename": "drf_util-0.0.8.tar.gz", "has_sig": false, "md5_digest": "3ae1675b9f3e73bfcc6a2ef74ddb3086", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 8103, "upload_time": "2019-03-27T14:20:34", "upload_time_iso_8601": "2019-03-27T14:20:34.138255Z", "url": "https://files.pythonhosted.org/packages/54/3e/346687be08a97d807d0086592923b75633676562f08cb7dc154511187f53/drf_util-0.0.8.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.9": [ { "comment_text": "", "digests": { "md5": "794c0920f760638cafe6010a7b850f32", "sha256": "d4106f410c77c7067f1902330b7ff48b2e988adf169db70df860a7fc8e065333" }, "downloads": -1, "filename": "drf_util-0.0.9.tar.gz", "has_sig": false, "md5_digest": "794c0920f760638cafe6010a7b850f32", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 8155, "upload_time": "2019-03-27T19:24:08", "upload_time_iso_8601": "2019-03-27T19:24:08.064678Z", "url": "https://files.pythonhosted.org/packages/2e/c4/c1d93c9ed78c8a424634fe9d6dac9283b9a73a772b4916f983e2f11cfacc/drf_util-0.0.9.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "f425efe341e45017358ab0a168992ee0", "sha256": "4a15ddacd1e8450a22fccf5642901257c9ec2f54cd2eab4ba624fb8e6541d592" }, "downloads": -1, "filename": "drf_util-1.0.0.tar.gz", "has_sig": false, "md5_digest": "f425efe341e45017358ab0a168992ee0", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22099, "upload_time": "2021-08-13T07:54:23", "upload_time_iso_8601": "2021-08-13T07:54:23.853150Z", "url": "https://files.pythonhosted.org/packages/04/e1/9a21d78b1c478d34b37783b2c1c0fc4249e6759b64f89520a625634c72b7/drf_util-1.0.0.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "ceb68be676a10d85e7b9bdcbecfcc952", "sha256": "cd3925ace35975d3b2e06bd7d5d6507f6d327f2b742b8940088989231d79fcd9" }, "downloads": -1, "filename": "drf_util-1.0.1.tar.gz", "has_sig": false, "md5_digest": "ceb68be676a10d85e7b9bdcbecfcc952", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22117, "upload_time": "2021-08-13T15:13:59", "upload_time_iso_8601": "2021-08-13T15:13:59.846055Z", "url": "https://files.pythonhosted.org/packages/f8/d8/8f26f097040ef0559ff914084abb8144fb8594ef95f753a0f6616d9e617a/drf_util-1.0.1.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.10": [ { "comment_text": "", "digests": { "md5": "d99355b1c1a5d91f8424dfccbb4c3754", "sha256": "1763c36da5547f7de73d8bc6d4b1fe30e2ea6043e281b48a6ca6f33b1f3ae179" }, "downloads": -1, "filename": "drf_util-1.0.10.tar.gz", "has_sig": false, "md5_digest": "d99355b1c1a5d91f8424dfccbb4c3754", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22905, "upload_time": "2021-11-09T07:00:46", "upload_time_iso_8601": "2021-11-09T07:00:46.789871Z", "url": "https://files.pythonhosted.org/packages/f5/00/45dfb6b69e9462e5977fa8d906b86f489429ff94aefc62d3d9c3e6d487a6/drf_util-1.0.10.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.11": [ { "comment_text": "", "digests": { "md5": "3180b0e00bc71f7f02cc3bce21e66ad8", "sha256": "49c74cb54ae43d92af11af414118174e45935afab50297d267af0d5c38fcc2bf" }, "downloads": -1, "filename": "drf_util-1.0.11.tar.gz", "has_sig": false, "md5_digest": "3180b0e00bc71f7f02cc3bce21e66ad8", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22915, "upload_time": "2021-11-23T08:25:13", "upload_time_iso_8601": "2021-11-23T08:25:13.418298Z", "url": "https://files.pythonhosted.org/packages/d4/b6/c66bf3687451ff2ee59fa2be4799395508e85c8fe386454209a86356e7dc/drf_util-1.0.11.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.12": [ { "comment_text": "", "digests": { "md5": "d1b84c2de8f88d813d4b7feb0fa26eb0", "sha256": "7fd8be41d3bc12b29d75345e03036371099e3c640cb26113e2163b61426e5246" }, "downloads": -1, "filename": "drf_util-1.0.12.tar.gz", "has_sig": false, "md5_digest": "d1b84c2de8f88d813d4b7feb0fa26eb0", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22932, "upload_time": "2021-12-08T14:49:08", "upload_time_iso_8601": "2021-12-08T14:49:08.407768Z", "url": "https://files.pythonhosted.org/packages/25/c9/5c016f46e0eec904dd8c7d1e37979fbfd6212373a83e32c39455ec2fffbb/drf_util-1.0.12.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.13": [ { "comment_text": "", "digests": { "md5": "b7ddec117e76cbf6413826d004010ce5", "sha256": "dfee08d5bdd9f9901cb9a9f664ea678a7d9bd71ac54b21872d96a08a7724cbc4" }, "downloads": -1, "filename": "drf_util-1.0.13.tar.gz", "has_sig": false, "md5_digest": "b7ddec117e76cbf6413826d004010ce5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 23559, "upload_time": "2021-12-30T07:33:38", "upload_time_iso_8601": "2021-12-30T07:33:38.675995Z", "url": "https://files.pythonhosted.org/packages/7c/b8/24043d197de48e378faa4710206ade44cd757bbbac82f2f7a0d8cd2103f1/drf_util-1.0.13.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.14": [ { "comment_text": "", "digests": { "md5": "6f64bb0c631df148b21ed2d27bc8cb96", "sha256": "22b58a67674fad43a482255035c4d6a00e95829849080dcfee943f7a1160d9db" }, "downloads": -1, "filename": "drf_util-1.0.14.tar.gz", "has_sig": false, "md5_digest": "6f64bb0c631df148b21ed2d27bc8cb96", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 23569, "upload_time": "2022-02-09T12:48:07", "upload_time_iso_8601": "2022-02-09T12:48:07.841534Z", "url": "https://files.pythonhosted.org/packages/90/3e/03bae55d9e7b8abae60b541cc7384328de865e5ce56e49b77f436b43728d/drf_util-1.0.14.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "db22c3bfbab1d4d36429f4e9c19c0be4", "sha256": "22b19ecbd4639b02e6dbd8ac0ab10959030f7b1a336eb6d3c349cc23c1377200" }, "downloads": -1, "filename": "drf_util-1.0.2.tar.gz", "has_sig": false, "md5_digest": "db22c3bfbab1d4d36429f4e9c19c0be4", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22180, "upload_time": "2021-08-19T05:39:19", "upload_time_iso_8601": "2021-08-19T05:39:19.366043Z", "url": "https://files.pythonhosted.org/packages/1e/d4/c728facfd918fdf05b8854dcc2c566dd677d4ce076568c7a81dd3afcfaa0/drf_util-1.0.2.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "03d009fe8df58662aa5373afe180dddd", "sha256": "63b4d47d1ee147614d1e61af545952e6e02702851c24c7176d68ae8e9b655b8e" }, "downloads": -1, "filename": "drf_util-1.0.3.tar.gz", "has_sig": false, "md5_digest": "03d009fe8df58662aa5373afe180dddd", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22166, "upload_time": "2021-08-19T07:31:09", "upload_time_iso_8601": "2021-08-19T07:31:09.983697Z", "url": "https://files.pythonhosted.org/packages/e1/9c/bfa239ad3c67c170cbb4d5a6d511598e3e0b40c2e2d65f8c9cdf821c72cb/drf_util-1.0.3.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.4": [ { "comment_text": "", "digests": { "md5": "9d7f13543e89a957e29cbfd36c625808", "sha256": "0c8d4292f1f056284f441d1ac4f539bcc5f174ef76d601cb5cc7ae5128644904" }, "downloads": -1, "filename": "drf_util-1.0.4.tar.gz", "has_sig": false, "md5_digest": "9d7f13543e89a957e29cbfd36c625808", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22163, "upload_time": "2021-10-05T10:33:36", "upload_time_iso_8601": "2021-10-05T10:33:36.630771Z", "url": "https://files.pythonhosted.org/packages/e4/c3/d0863c120e3a56003f53b74be2689f5ace5160af23918653a42a82c23946/drf_util-1.0.4.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.5": [ { "comment_text": "", "digests": { "md5": "380de6430d12d42fc35c432dffa3125a", "sha256": "feb7a2e714c69757031cb957827cb23f34a278bec62336ad33df510a75a946f1" }, "downloads": -1, "filename": "drf_util-1.0.5.tar.gz", "has_sig": false, "md5_digest": "380de6430d12d42fc35c432dffa3125a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22276, "upload_time": "2021-10-07T09:31:40", "upload_time_iso_8601": "2021-10-07T09:31:40.545650Z", "url": "https://files.pythonhosted.org/packages/3a/9b/90ecbaff402875e14872a2df36c078a4bea166df161ca21ac1cb39a04182/drf_util-1.0.5.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.6": [ { "comment_text": "", "digests": { "md5": "fe1cecb17d66d27f37ac578c467b6342", "sha256": "6445d3600adfd29dabd394b92d8e2d051dcc9d902723e51680e85b1eee90e832" }, "downloads": -1, "filename": "drf_util-1.0.6.tar.gz", "has_sig": false, "md5_digest": "fe1cecb17d66d27f37ac578c467b6342", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22282, "upload_time": "2021-10-28T12:42:59", "upload_time_iso_8601": "2021-10-28T12:42:59.746314Z", "url": "https://files.pythonhosted.org/packages/f1/b7/369c94f2bd7d55e694979f775eacdb100330e708ab9d1c7dca69e5acac2c/drf_util-1.0.6.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.7": [ { "comment_text": "", "digests": { "md5": "7e57274c657d46451d7556c6a7973ebf", "sha256": "b70f5e07d5df42178a1c18c20dc1c2d6d11a82d4a204d8da444ad55b37c885aa" }, "downloads": -1, "filename": "drf_util-1.0.7.tar.gz", "has_sig": false, "md5_digest": "7e57274c657d46451d7556c6a7973ebf", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22308, "upload_time": "2021-11-01T20:27:18", "upload_time_iso_8601": "2021-11-01T20:27:18.587653Z", "url": "https://files.pythonhosted.org/packages/f7/57/600827361a95464e50af409b8b14dffc5a4a8d38548487995259280915c7/drf_util-1.0.7.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.8": [ { "comment_text": "", "digests": { "md5": "f65e29ea1a60f2b9b71c7bd03512a56b", "sha256": "8dc95fcbeca2c9a134037d14287ecf48b83ec70c9ae5b23561197f5ada32962b" }, "downloads": -1, "filename": "drf_util-1.0.8.tar.gz", "has_sig": false, "md5_digest": "f65e29ea1a60f2b9b71c7bd03512a56b", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22847, "upload_time": "2021-11-05T16:00:49", "upload_time_iso_8601": "2021-11-05T16:00:49.676070Z", "url": "https://files.pythonhosted.org/packages/7f/54/f81efc19ef4097401b0cd3c468966cddb86acf0bab9dffe0965e5501511b/drf_util-1.0.8.tar.gz", "yanked": false, "yanked_reason": null } ], "1.0.9": [ { "comment_text": "", "digests": { "md5": "625e9fc6fe6d5e26dbb99cfde413b603", "sha256": "eea9c19aec4c580aefc45e6973189912a9225f1d2e095ea8ffd29032fa8115d4" }, "downloads": -1, "filename": "drf_util-1.0.9.tar.gz", "has_sig": false, "md5_digest": "625e9fc6fe6d5e26dbb99cfde413b603", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 22855, "upload_time": "2021-11-08T07:15:16", "upload_time_iso_8601": "2021-11-08T07:15:16.951031Z", "url": "https://files.pythonhosted.org/packages/f2/62/ef3bea3f22c34ff4b197aa25ef6e74d0d40e943542c5e9fec53117b29fa4/drf_util-1.0.9.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "6f64bb0c631df148b21ed2d27bc8cb96", "sha256": "22b58a67674fad43a482255035c4d6a00e95829849080dcfee943f7a1160d9db" }, "downloads": -1, "filename": "drf_util-1.0.14.tar.gz", "has_sig": false, "md5_digest": "6f64bb0c631df148b21ed2d27bc8cb96", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4", "size": 23569, "upload_time": "2022-02-09T12:48:07", "upload_time_iso_8601": "2022-02-09T12:48:07.841534Z", "url": "https://files.pythonhosted.org/packages/90/3e/03bae55d9e7b8abae60b541cc7384328de865e5ce56e49b77f436b43728d/drf_util-1.0.14.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }