Full Code of wuhan2020/api-server for AI

master 19b784d5e8f1 cached
46 files
72.1 KB
22.8k tokens
32 symbols
1 requests
Download .txt
Repository: wuhan2020/api-server
Branch: master
Commit: 19b784d5e8f1
Files: 46
Total size: 72.1 KB

Directory structure:
gitextract_rth757f3/

├── .dockerignore
├── .github/
│   ├── hypertrons.json
│   ├── pull_request_template.md
│   └── workflows/
│       └── pythonapp.yml
├── .gitignore
├── .gitmodules
├── .python-version
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README-cn.md
├── README.md
├── bootstrap
├── config/
│   ├── dev.py
│   ├── product.py
│   └── settings.py
├── const.py
├── requirements.txt
├── src/
│   ├── __init__.py
│   ├── api/
│   │   ├── __init__.py
│   │   ├── accommodations.py
│   │   └── hospitals.py
│   ├── core/
│   │   └── __init__.py
│   ├── main.py
│   ├── swagger/
│   │   ├── accommodations.yml
│   │   ├── api.yml
│   │   ├── archived/
│   │   │   ├── accomodation.yaml
│   │   │   ├── donation.yaml
│   │   │   ├── hospitaldemands.yaml
│   │   │   ├── supplies.yaml
│   │   │   └── suppliesunits.yaml
│   │   ├── errors.yml
│   │   ├── hospitals.yml
│   │   └── validations.yaml
│   ├── tests/
│   │   ├── __init__.py
│   │   ├── data/
│   │   │   ├── csv/
│   │   │   │   ├── DONATION.csv
│   │   │   │   ├── FACTORY.csv
│   │   │   │   ├── HOSPITAL.csv
│   │   │   │   ├── HOTEL.csv
│   │   │   │   └── LOGISTICAL.csv
│   │   │   ├── test.json
│   │   │   └── test.xml
│   │   └── test_nothing.py
│   └── utils/
│       └── __init__.py
├── tools.py
└── utils.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
README.md
README-en.md
CONTRIBUTING.md


================================================
FILE: .github/hypertrons.json
================================================
{
  "label_setup": {
    "version": 1,
    "labels": [
      {
        "__merge__": true
      },
      {
        "name": "pull/approved",
        "description": "If a pull is approved, it will be automatically merged",
        "color": "008672"
      }
    ]
  },
  "role": {
    "version": 1,
    "roles": [
      {
        "name": "replier",
        "description": "Replier is responsible for reply issues in time",
        "users": [
          "LiuChangFreeman",
          "JamesBonddu"
        ],
        "commands": []
      },
      {
        "name": "approver",
        "description": "After approvers' approve, pulls should be merged automatically",
        "users": [
          "LiuChangFreeman",
          "JamesBonddu"
        ],
        "commands": [
          "/approve"
        ]
      },
      {
        "name": "author",
        "description": "Author of the issue or pull",
        "users": [],
        "commands": []
      },
      {
        "name": "notauthor",
        "description": "Not author of the issue or pull",
        "users": [],
        "commands": [
          "/approve"
        ]
      },
      {
        "name": "anyone",
        "description": "Anyone",
        "users": [],
        "commands": [
          "/self-assign"
        ]
      }
    ]
  },
  "command": {
    "version": 1,
    "commands": [
      {
        "name": "/approve",
        "scopes": [
          "review",
          "review_comment",
          "pull_comment"
        ]
      }
    ]
  },
  "approve": {
    "version": 1
  },
  "auto_merge": {
    "version": 1,
    "sched": "0 */5 * * * *"
  },
  "issue_reminder": {
    "version": 1
  },
  "auto_label": {
    "version": 1
  },
  "self_assign": {
    "version": 1
  },
  "weekly_report": {
    "version": 1,
    "generateTime": "0 0 12 * * 1"
  }
}


================================================
FILE: .github/pull_request_template.md
================================================
### Purpose | 本PR解决的问题
<!-- Please include the GitHub issue this fixes or resolves, if applicable, please also explain any extra purpose of this PR  -->
<!-- 请在下方附上本PR解决或实现的Issue编号, 例如 `#1`. 此外如果有, 请尽可能阐述本PR除issue所描述之外的目的 -->

- Closes #

### Changes | 本PR的更改
<!-- Please list out what major changes were made in this PR to address the issue: -->
<!-- 请尽可能详细的列出本PR的主要更改 -->

- No changes.


================================================
FILE: .github/workflows/pythonapp.yml
================================================
name: Tests on Pull Requests and Master

on:
  push:
    branches:
      - master
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repo
      uses: actions/checkout@v2

    - name: Set up Python 3.6
      uses: actions/setup-python@v1
      with:
        python-version: 3.6

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt

    - name: Lint with flake8
      run: |
        pip install flake8
        # stop the build if there are Python syntax errors or undefined names
        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
        # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

    - name: Test with pytest
      run: |
        pip install pytest
        pytest -v src/tests


================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
*.pyc
__pycache__/
.vscode/
.idea/
.venv/
.env
*.swp
auth/


================================================
FILE: .gitmodules
================================================
[submodule "wuhan2020"]
	path = wuhan2020
	url = git@github.com:wuhan2020/wuhan2020.git


================================================
FILE: .python-version
================================================
3.6.10


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing Guide

## Structure

![Tech Arch Diagram](https://www.lucidchart.com/publicSegments/view/6ab27659-257a-44ce-a478-46dad3328b9c/image.png)

As the above Tech Arch diagram shows (dot-line entities mean they are not there yet), this project is purely data-driven and the core layout looks like the following:

```
src
├── __init__.py
├── api/
├── core/
├── main.py
├── swagger/
├── tests/
└── utils/
```

`main.py` is the entry point of the services and it helps:
- glue all sub API YML files together to an aggregated YML
- send the YML to connection which renders the Swagger UI and applies the API resolvers.
- load required service-level connfigurations (such as debug, logging, path to the data sources, etc.).

### To add new or edit on existing API endpoint(s)

In general you need to edit the `src/swagger/api.yml` and probably its dependencies (such as `donation.yml`). **Be aware that any changes to the YML files can change the data model and breaks the system and the API consumers.**

If you are using a local Python3.6 environment, setting `debug=True` in `main.py` will help you see the changes you made in the Swagger UI in real time. 

Be aware that the `operationId` field in the YML files works as automatic routers that map your endpoint to your Python views functions. To make the endpoints functional, you also have to add/edit the functions in `src/api`. The results of the functions need to be consistent with the data model defined in the API YML file(s).

## Development

![DevOps Pipeline](https://www.lucidchart.com/publicSegments/view/b853bf49-31fa-46ba-b732-2eb9de8a2cf8/image.png)

The above diagram shows how to work on this repo:

### Development Process

The development process of this project requires every contributor to fork the repo and only make PRs from the fork to `master` branch. 

#### Setup upstream

From within your fork, use:
```
git remote add upstream git@github.com:wuhan2020/api-server.git
```
to setup this repo as the `upstream`.

#### Keep up-to-date with the upstream

Everytime before you want to make new changes to the repo, use:
```
git fetch upstream
git rebase upstream/master
```
to update your fork with latest changes that have merged to `upstream`'s `master` branch.

#### Address comments
Once you have finished committing and pushing your changes to your remote fork, please create a PR from your remote repo following the PR template. One of the maintainers of the repo will review and merge your PR. Please note PR that fails the tests cannot be reviewed or merged.

## Deployment

The current deployment is under construction and subjects to change. New documentation is coming soon...


================================================
FILE: Dockerfile
================================================
# Align with the CI/CD YML
# We cannot use alpine since
# we need to call bash in entrypoint
FROM python:3.6

# Setup workdir
WORKDIR /api-server

# Copy src files
COPY . .

# Install deps
RUN pip install -r requirements.txt

# Expose port 5000
EXPOSE 9000

# Start the server
ENTRYPOINT [ "bash", "bootstrap"]


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 援助武汉

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.


================================================
FILE: README-cn.md
================================================
# API Server

![Python3.6](https://img.shields.io/badge/python-3.6-green.svg?style=flat-square&logo=python&colorB=blue)
[![Slack Channel](https://img.shields.io/badge/Slack%20Channel-%23api--server-green.svg?style=flat-square&colorB=blue)](https://app.slack.com/client/TT5U1VCPQ/CT3V5CDKJ)
[![Built with love](https://img.shields.io/badge/BUILT%20WITH-LOVE-orange?style=flat-square)](https://img.shields.io/badge/BUILT%20WITH-LOVE-orange?style=flat-square&logo=love)
![Build Status](https://github.com/wuhan2020/api-server/workflows/Tests%20on%20Pull%20Requests%20and%20Master/badge.svg?branch=master&event=push)

[English Version](README.md)

这是一个为了抗击在武汉乃至全球爆发的新型冠状病毒而建设的志愿信息收集和分享平台的后端API服务。

此API使用Python 和 Flask 编写,意在轻量化和无状态,通过标准的RESTFul接口传输依靠从其他子项目收集并验证的数据。

## 快速上手

克隆此仓库及子模块仓库:
```
git clone https://github.com/wuhan2020/api-server
cd api-server
git clone https://github.com/wuhan2020/wuhan2020
```

### 在本地 Docker 容器运行(推荐)

首先,你需要安装[Docker客户端](https://www.docker.com/products/docker-desktop).

#### 构建 Docker 镜像 

在克隆的本仓库根目录下运行:
```
docker build -t api-server:default .
```
* 注意:这一步耗时取决于所在国家或地区

#### 运行已构建的 Docker 镜像

运行:
```
docker run --name api-server --publish 9000:9000 api-server:default 
```
然后在浏览器中打开 `http://localhost:9000`  。(使用 `-d` 来以后台模式(Detached mode)运行 Docker 容器)

在这一步后你应该可以看到记录了可用的端点的Swagger页面。

如果出现 `The container name "/api-server" is already in use` 报错可先执行 `docker rm api-server` 删除残留的同名容器.

#### 停止运行中的 Docker 容器

运行:
```
docker stop api-server 
```
停止运行中的容器.

### 在Python环境中运行

确保你已经安装 **Python3.6**  (一般来讲你应该会使用 [VirtualEnv](https://docs.python.org/3.6/tutorial/venv.html)
或是 [PyEnv](https://github.com/pyenv/pyenv)). 然后在克隆仓库的根目录运行:

```
pip install -U -r requirements.txt
```

启动服务器:

```
bash bootstrap
```
在浏览器中打开`http://localhost:9000`,你应该可以看到记录了可用的端点的Swagger页面。.


## 开发

待更新...

## 部署
待更新...

## 贡献

参照[贡献指南](CONTRIBUTING.md)

## 前端issues

请查阅[这里](https://github.com/wuhan2020/front-pages/issues)


================================================
FILE: README.md
================================================
# API Server

![Python3.6](https://img.shields.io/badge/python-3.6-green.svg?style=flat-square&logo=python&colorB=blue)
[![Slack Channel](https://img.shields.io/badge/Slack%20Channel-%23api--server-green.svg?style=flat-square&colorB=blue)](https://app.slack.com/client/TT5U1VCPQ/CT3V5CDKJ)
[![Built with love](https://img.shields.io/badge/BUILT%20WITH-LOVE-orange?style=flat-square)](https://img.shields.io/badge/BUILT%20WITH-LOVE-orange?style=flat-square&logo=love)
![Build Status](https://github.com/wuhan2020/api-server/workflows/Tests%20on%20Pull%20Requests%20and%20Master/badge.svg?branch=master&event=push)

[中文文档](README-cn.md)

This a backend API service of the voluntary information collection and sharing platform to fight against the 2019-nCoV outbreak in Wuhan and the world. 

The API is designed to be thin and stateless. It relies on the data collected and validated by other sub-projects, transform and expose them through standard RESTful APIs. The service is written in Python and Flask.

![Tech Arch Diagram](https://www.lucidchart.com/publicSegments/view/6ab27659-257a-44ce-a478-46dad3328b9c/image.png)

## Get Started

Please first clone this repository and the sub-module-repo by:

```
git clone https://github.com/wuhan2020/api-server
cd api-server
git clone https://github.com/wuhan2020/wuhan2020
```

### Running locally with Docker (Recommended)

**Pre-requisite: You have to have [Docker client](https://www.docker.com/products/docker-desktop) installed on your machine.**

#### Build the Docker image

Run:
```
docker build -t api-server:default .
```
from the root directory of the clone of this repo. Note this step could take a long time depends on where you are located in.

#### Run built Docker image

Run:
```
docker run --name api-server --publish 9000:9000 api-server:default 
```
and then open `http://localhost:9000` in your browser. _(Add `-d` to run the Docker container in detach/background mode)_

You should see a Swagger page documents the available endpoints now.

_If you ran into error `The container name "/api-server" is already in use`, please run `docker rm api-server` to delete previous container which has the same name._

#### Stop running Docker container

Run:
```
docker stop api-server 
```
to stop the running container.

### Running with your own Python environment

Please make sure you have **Python3.6** installed, (ideally you should be using a [VirtualEnv](https://docs.python.org/3.6/tutorial/venv.html)
or something like [PyEnv](https://github.com/pyenv/pyenv)). Then from the root directory of the cloned repo, run:

```
pip install -U -r requirements.txt
```

and then start the server by:

```
bash bootstrap
```
now if you open `http://localhost:9000` in your browser, you should see a Swagger page documents the available endpoints.

## Contributing Guide

Please see [Conntributing Guide](CONTRIBUTING.md) for more information about this project.

## Front-end issues

Please check [here](https://github.com/wuhan2020/front-pages/issues)


================================================
FILE: bootstrap
================================================
#!/bin/bash
python3 -m "src.main"


================================================
FILE: config/dev.py
================================================


================================================
FILE: config/product.py
================================================


================================================
FILE: config/settings.py
================================================
import os, sys

DEBUG_FLAG = True


def get_cache_path():
    path_home = './'
    if DEBUG_FLAG:
        path_home = os.path.join(path_home, 'test/data/')
    else:
        path_home = os.path.join(path_home, 'wuhan2020/data/')
    # wuhan2020文件夹为https://github.com/wuhan2020/wuhan2020项目文件的本地clone
    # 阿里云serverless使用挂载nas远程目录来存放缓存文件;在本机调试时,缓存文件夹将存放在项目根目录
    if not os.path.exists(path_home):
        os.mkdirs(path_home)
    return path_home


class Config(object):
    DEBUG = DEBUG_FLAG
    # 使用aliyun默认端口9000
    ENV = {
        "FC_SERVER_PORT": 9000,
    }


class CacheCfg(Config):
    CACHE_DIR = get_cache_path()
    # csv
    CSV_CACHE = CACHE_DIR + 'csv/'
    HOSPITAL_PATH = os.path.join(CSV_CACHE, "HOSPITAL.csv")
    HOTEL_PATH = os.path.join(CSV_CACHE, "HOTEL.csv")
    LOGISITICAL_PATH = os.path.join(CSV_CACHE, "LOGISTICAL.csv")
    NEWS_PATH = os.path.join(CSV_CACHE, "NEWS.csv")
    DONATION_PATH = os.path.join(CSV_CACHE, "DONATION.csv")
    FACTORY_PATH = os.path.join(CSV_CACHE, "FACTORY.csv")
    CLINIC_PATH = os.path.join(CSV_CACHE, "CLINIC.csv")
    # json
    JSON_CACHE = CACHE_DIR + 'json/'
    JSON_HOSPITAL_PATH = os.path.join(JSON_CACHE, "HOSPITAL.json")
    JSON_HOTEL_PATH = os.path.join(JSON_CACHE, "HOTEL.json")
    JSON_LOGISITICAL_PATH = os.path.join(JSON_CACHE, "LOGISTICAL.json")
    JSON_NEWS_PATH = os.path.join(JSON_CACHE, "NEWS.json")
    JSON_DONATION_PATH = os.path.join(JSON_CACHE, "DONATION.json")
    JSON_FACTORY_PATH = os.path.join(JSON_CACHE, "FACTORY.json")
    JSON_CLINIC_PATH = os.path.join(JSON_CACHE, "CLINIC.json")


================================================
FILE: const.py
================================================
"""
SUB HEADERS
TODO: change to en
"""
factory_medical_supplies = [
    # 口罩
    ('普通医用口罩', 'YY/T 0969-2013'),
    ('医用外科口罩', 'YY 0469-2010'),
    ('医用防护口罩 | N95口罩', 'GB 19083-2010, 建议3M 1860/1870/9123,防飞沫血液体液款'),
    # 面罩
    ('防冲击眼罩/护目镜/防护眼镜', 'GB 19083-2010, 建议3M 1860/1870/9123,防飞沫血液体液款'),
    ('防护面罩', 'GB 19083-2010, 建议3M 1860/1870/9123,防飞沫血液体液款'),
    ('防护帽/医用帽/圆帽', 'GB 19083-2010, 建议3M 1860/1870/9123,防飞沫血液体液款'),
    # 衣物
    ('隔离衣', ''),
    ('防护服', 'GB 19082-2003'),
    ('手术衣', ''),
    # 手套
    ('乳胶手套', '灭菌,GB 10213-2006'),
    # 鞋
    ('长筒胶鞋/防污染靴', ),
    ('防污染鞋套', ),
    ('防污染靴套', ),
    # 消毒耗材
    ('84消毒液', ),
    ('过氧乙酸', ),
    ('75%酒精', ),
    ('手部皮肤消毒液', ),
    ('活力碘', ),
    # 其它耗材
    ('床罩', ),
    ('医用面罩式雾化器', ),
    ('测体温设备', ),
    ('空气消毒设备', ),
    ('医用紫外线消毒车', ),
]

"""
CSV HEADERS
"""
DONATION_HEADERS = [
    'donate_sorce',
    'donate_way',
    'donate_link',
    'donate_account_info',
    'donate_cur_status',
    'donate_audit_status',
    'donate_audit_person',
]
FACTORY_HEADERS = [
    'factory_prov',
    'factory_name',
    factory_medical_supplies,
    'factory_qualification',
    'factory_addr',
    'factory_contact',
    'factory_note',
    'factory_link',
    'factory_audit_status',
    'factory_reviewer',
]
CLINIC_HEADERS = [
    'clinic_unit',
    'clinic_contact',
    'clinic_note'
]
HOTEL_HEADERS = [
    'hotel_name',
    'hotel_prov',
    'hotel_addr',
    'hotel_room_num',
    'hotel_acceptable_num',
    'hotel_supplier',
    'hotel_concat_person',
    'hotel_concat_phone',
    'hotel_note',
    'hotel_link',
    'hotel_audit_status',
    'hotel_audit_person',
]
LOGISTICS_HEADERS = [
    'logistics_name',
    'logistics_area',
    'logistics_power',
    'logistics_link',
    'logistics_contact'
]
NEWS_HEADERS = [
    'news_title',
    'news_summary',
    'news_time',
    'news_link'
]
HOSPITAL_HEADERS = [
    'hospital_prov',
    'hospital_name',
    factory_medical_supplies,
    'hospital_link',
    'hospital_addr',
    'hospital_contact',
    'hospital_note',
    'hospital_audit_status',
    'hospital_audit_person',
]


================================================
FILE: requirements.txt
================================================
Flask==1.1.1
PyYAML==5.3
flask-swagger==0.2.14
xmltodict==0.12.0
Flask-HTTPAuth==3.3.0
connexion[swagger-ui]==2.6.0
prance==0.18.1


================================================
FILE: src/__init__.py
================================================


================================================
FILE: src/api/__init__.py
================================================


================================================
FILE: src/api/accommodations.py
================================================
def get_all():
    """List all available accomodations."""
    return {}


def get_by_name():
    """Search for accomodations by name."""


================================================
FILE: src/api/hospitals.py
================================================
def get_all():
    """List all available hospitals."""
    return {}


def add():
    """Add new hospitals."""
    return {}


================================================
FILE: src/core/__init__.py
================================================


================================================
FILE: src/main.py
================================================
import argparse
import flask
from flask import Flask
from flask import Response as ResponseBase
import connexion
from swagger_ui_bundle import swagger_ui_3_path
import os
from connexion.resolver import RestyResolver
import prance
from pathlib import Path
from typing import Dict, Any


parser = argparse.ArgumentParser()
parser.add_argument('--host', default='0.0.0.0')
parser.add_argument('--port', type=int, default=9000)
args, _ = parser.parse_known_args()


def aggregate_specs(main_file: Path) -> Dict[str, Any]:
    """This function glues all seperate API Spec YML files together.

    This enales we keep a set of small YML files while being able
    to use something like $ref: 'another.yaml#/components/schemas/Foo'
    in the YML files.
    """
    parser = prance.ResolvingParser(str(main_file.absolute()), lazy=True, strict=True)
    parser.parse()
    return parser.specification


# Use OpenAPI Swagger page, and redirct SwaggerUI to root
options = {'swagger_path': swagger_ui_3_path, "swagger_url": ""}

# Note this app is a wrapper around FlaskAPP, use app.app to access
# the actual Flask app
app = connexion.App(__name__, options=options)
app.add_api(
    aggregate_specs(Path(__file__).parent / "swagger/api.yml"),
    validate_responses=True,
    resolver=RestyResolver('src.api'),
)


def handler(environ, start_response) -> flask.Flask:
    """This function is required by the deployment.

    For more information, check here:
    https://www.alibabacloud.com/help/doc-detail/74756.htm?spm=a2c63.l28256.a3.18.a2543c943bYfKr
    """
    # do something here
    return app(environ, start_response)


if __name__ == "__main__":
    app.run(host=args.host, port=os.environ.get("FC_SERVER_PORT", args.port), debug=False)


================================================
FILE: src/swagger/accommodations.yml
================================================
paths:
  /accommodation/all:
    get:
      tags:
        - Wuhan2020 Data
      summary: Search for all available accommodations
      operationId: src.api.accommodations.get_all
      description: |
        By passing in the appropriate options, 
        you can get all of the available accommodations
        or query for specific accommodations in the system
      parameters:
        - in: query
          name: skip
          description: number of records to skip for pagination
          schema:
            type: integer
            format: int32
            minimum: 0
            default: 0
        - in: query
          name: limit
          description: maximum number of records to return
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 50
            default: 50
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/AccommodationItem"
        "400":
          $ref: "errors.yml#/components/BadRequest"
        "500":
          $ref: "errors.yml#/components/InternalServerError"
        # Definition of all other error statuses
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "errors.yml#/components/schemas/Error"
components:
  schemas:
    AccommodationItem:
      type: object
      required:
        - id
        - name
        - address
        - volume
        - supportType
        - contact
        - validation
      properties:
        id:
          type: string
          format: uuid
          example: d290f1ee-6c54-4b01-90e6-d701748f0851
        name:
          type: string
          example: 第一大酒店
        address:
          type: string
          example: 湖北省武汉市靖江大街12号 第一大酒店
        supportType:
          type: string
          enum:
            [
              "医护人员",
              "运输司机",
              "需隔离观察人员",
              "支援人员",
              "外出滞留人员",
            ]
        contact:
          $ref: "validations.yaml#/components/schemas/Contact"
        validation:
          $ref: "validations.yaml#/components/schemas/ValidationItem"
        volume:
          type: object
          required:
            - totalPeople
          properties:
            maxCapacity:
              type: integer
              format: int32
              example: 55
              description: 最多可接纳55人
            rooms:
              type: array
              items:
                type: object
                required:
                  - number
                  - room
                properties:
                  number:
                    type: integer
                    format: int32
                    example: 5
                    description: 5间
                  room:
                    $ref: "#/components/schemas/AccomodationRoom"
        releaseDate:
          type: string
          format: date-time
          example: "2020-01-01T09:12:33.001Z"
        availableState:
          oneOf:
            - type: boolean
              default: true
            - $ref: "validations.yaml#/components/schemas/SuspendItem"
    AccomodationRoom:
      type: object
    required:
      - capacity
    properties:
      capacity:
        type: integer
        format: int32
        example: 2
        description: 做多可接纳2个人
      space:
        type: number
        format: float
        example: 5.2
        description: 5.2 平方米
      roomtype:
        type: string
        enum: ["单人间", "双人间", "多人间", "标准间", "套房", "豪华套房", "总统套房", "钟点房", "其他"]


================================================
FILE: src/swagger/api.yml
================================================
openapi: 3.0.2
info:
  title: Wuhan2020 API service
  description: This is the API service of the Wuhan2020 project, which aims at collecting all useful information to help people fight against the 2019-nCoV outbreak, check the developer website for more info
  version: 0.1.0
  contact:
    name: "Github Repo"
    url: https://github.com/wuhan2020/api-server

# Let's version the APIs a bit later
# servers:
#   - url: /api/v1

tags:
  - name: Wuhan2020 Data
    description: Get data that's collected and validated by Wuhan2020 volunteers

# Refer to https://swagger.io/docs/specification/using-ref/ for Escape Characters e.g. ~1
paths:
  /accommodation/all:
    $ref: "accommodations.yml#/paths/~1accommodation~1all"
  /hospital/all:
    $ref: "hospitals.yml#/paths/~1hospital~1all"
components:
  schemas:
    AccommodationItem:
      $ref: "accommodations.yml#/components/schemas/AccommodationItem"
    HospitalItem:
      $ref: "hospitals.yml#/components/schemas/HospitalItem"


================================================
FILE: src/swagger/archived/accomodation.yaml
================================================
openapi: 3.0.2
info:
  description: This API provides Hotel/motel/ Accomodation list
  version: 0.1.0
  title: Accomodation List API
  contact:
    email: wuhan2020@your-company.com
  license:
    name: Apache 2.0
    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
tags:
  - name: contributors
    description: Secured write permission calls
  - name: developers
    description: Operations available to regular developers
paths:
  /acomodations:
    get:
      tags:
        - developers
      summary: searches accomodations
      operationId: searchAccomodations
      description: |
        By passing in the appropriate options, you can search for
        available accomodations in the system
      parameters:
        - in: query
          name: searchString
          description: pass an optional search string for looking up accomodations
          required: false
          schema:
            type: string
        - in: query
          name: skip
          description: number of records to skip for pagination
          schema:
            type: integer
            format: int32
            minimum: 0
        - in: query
          name: limit
          description: maximum number of records to return
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 50
      responses:
        '200':
          description: search results matching criteria
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/AccomodationItem'
        '400':
          description: bad input parameter
    post:
      tags:
        - contributors
      summary: adds am accomodation item
      operationId: addAccomodation
      description: Adds an item to the system
      responses:
        '201':
          description: item created
        '400':
          description: 'invalid input, object invalid'
        '409':
          description: an existing item already exists
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AccomodationItem'
        description: Accomodation item to add
    put:
      tags:
      - contributors
      summary: suspend am accomodation item
      operationId: suspendAccomodation
      description: suspend an item to the system
      responses:
        '201':
          description: item suspended
        '400':
          description: 'invalid input, object invalid'
        '403':
          description: 'forbidden'
        '404':
          description: 'not found'
      requestBody:
        content:
          application/json:
            schema:
              $ref: 'validations.yaml#/components/schemas/SuspendItem'
servers:
  - url: 'https://virtserver.swaggerhub.com/wuhan2020/accomodations/0.1.0'
components:
  schemas:
    AccomodationItem:
      type: object
      required:
        - id
        - name
        - address
        - volume
        - supporttype
        - contact
        - validation
      properties:
        id:
          type: string
          format: uuid
          example: d290f1ee-6c54-4b01-90e6-d701748f0851
        name:
          type: string
          example: 第一大酒店
        address:
          type: string
          example: 湖北省武汉市靖江大街12号 第一大酒店
        supporttype:
          type: string
          enum: ['医护人员','运输司机','需隔离观察人员','支援人员','外出滞留人员']
        contact:
          $ref: 'validations.yaml#/components/schemas/Contact'
        validation:
          $ref: 'validations.yaml#/components/schemas/ValidationItem'
        volume:
          type: object
          required:
            - totalPpl         
          properties:
            totalPpl:
              type: integer
              format: int32
              example: 55
              description: 共可接纳55人
            rooms:
              type: array
              items:
                type: object
                required:
                  - number
                  - room
                properties:
                  number:
                    type: integer
                    format: int32
                    example: 5
                    description: 5间
                  room:  
                    $ref: '#/components/schemas/AccomodationRoom'
        releaseDate:
          type: string
          format: date-time
          example: '2016-08-29T09:12:33.001Z'
        availableState:
          oneOf:
          - type: boolean
            default: true
          - $ref: 'validations.yaml#/components/schemas/SuspendItem'
    AccomodationRoom:
      type: object
      required:
        - ppl
      properties:
        ppl:
          type: integer
          format: int32
          example: 2
          description: 2个人 
        space:
          type: number
          format: float
          example: 5.2
          description: 5.2 平方米
        roomtype:
          type: string
          enum: ['双人间','多人间','标准间','套房','豪华套房','总统套房']

================================================
FILE: src/swagger/archived/donation.yaml
================================================
openapi: 3.0.2
info:
  description: This API provides Donation list
  version: 0.2.0
  title: Donation List API
  contact:
    email: wuhan2020@your-company.com
  license:
    name: Apache 2.0
    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
tags:
  - name: contributors
    description: Secured write permission calls
  - name: developers
    description: Operations available to regular developers
paths:
  /donation:
    get:
      tags:
        - developers
      summary: searches donation
      operationId: searchDonation
      description: |
        By passing in the appropriate options, you can search for
        available inventory in the system
      parameters:
        - in: query
          name: searchString
          description: pass an optional search string for looking up inventory
          required: false
          schema:
            type: string
        - in: query
          name: skip
          description: number of records to skip for pagination
          schema:
            type: integer
            format: int32
            minimum: 0
        - in: query
          name: limit
          description: maximum number of records to return
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 50
      responses:
        '200':
          description: search results matching criteria
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/DonationItem'
        '400':
          description: bad input parameter
    post:
      tags:
        - contributors
      summary: adds a donation item
      operationId: addDonation
      description: Adds an item to the system
      responses:
        '201':
          description: item created
        '400':
          description: 'invalid input, object invalid'
        '409':
          description: an existing item already exists
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DonationItem'
        description: Donation item to add
servers:
  - url: 'https://virtserver.swaggerhub.com/wuhan2020/donation/0.2.0'
components:
  schemas:
    DonationItem:
      type: object
      required:
        - id
        - source
        - donate_way
        - offical_link
        - contact
        - cur_status
        - source_link
        - audit_status
        - update_time
      properties:
        id:
          type: string
          format: uuid
          example: d290f1ee-6c54-4b01-90e6-d701748f0851
        source:
          type: string
          example: 红十字会
        donate_way:
          type: string
          example: 支付宝
        offical_link:
          type: string
          format: uri
          example: https://mp.weixin.qq.com/s/qGAsMA4hsduP99CaabdQDg
        contact:
          type: array
          items:
            $ref: '#/components/schemas/ContactItem'
        cur_status:
          type: string
          example: 已捐赠; 筹款中;
        source_link:
          type: string
          format: uri
          example: https://mp.weixin.qq.com/s/qGAsMA4hsduP99CaabdQDg
        audit_status:
          type: string
          example: 已审计; 审计中;
        update_time:
          type: string
          format: date-time
          example: '2020-01-23T09:12:33.001Z'
    ContactItem:
      type: object
      required:
        - name
        - phone
      properties:
        name:
          type: string
          example: xxx
        phone:
          type: string
          example: 12315


================================================
FILE: src/swagger/archived/hospitaldemands.yaml
================================================
openapi: 3.0.2
info:
  description: This is Hostpital Demands API

  version: 0.2.0

  title: Hostpital Demands API
  # put the contact info for your development or API team
  contact:
    email: wuhan2020@inrganizing operations
tags:
- name: contributors
  description: Secured write permission calls
- name: developers
  description: Operations available to regular developers

paths:
  /hospitaldemands:
    get:
      tags:
      - developers
      summary: searches hospital demands
      operationId: searchHospitalDemands
      description: |
        By passing in the appropriate options, you can search for
        recorded hospital demands in the system
      parameters:
        - in: query
          name: searchString
          description: pass an optional search string for looking up hospital demands
          required: false
          schema:
            type: string
        - in: query
          name: skip
          description: number of records to skip for pagination
          schema:
            type: integer
            format: int32
            minimum: 0
        - in: query
          name: limit
          description: maximum number of records to return
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 50
      responses:
        '200':
          description: search results matching criteria
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/HospitalDemandItem'
      
        '400':
          description: bad input parameter
    post:
      tags:
      - contributors
      summary: adds an hospital demands item
      operationId: addHospitalDemands
      description: Adds an item to the system
      responses:
        '201':
          description: item created
        '400':
          description: 'invalid input, object invalid'
        '409':
          description: an existing item already exists
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HospitalDemandItem'
        description: Hospital Demands item to add
    put:
      tags:
      - contributors
      summary: suspend an hospital demands item
      operationId: suspendHospitalDemands
      description: suspend an item to the system
      responses:
        '201':
          description: item suspended
        '400':
          description: 'invalid input, object invalid'
        '403':
          description: 'forbidden'
        '404':
          description: 'not found'
      requestBody:
        content:
          application/json:
            schema:
              $ref: 'validations.yaml#/components/schemas/SuspendItem'
        description: Hospital Demands item to suspend 取消医院需求item        

servers:
  - url: 'https://virtserver.swaggerhub.com/wuhan2020/hospitaldemands/0.2.0'
components:
  schemas:
    HospitalDemandItem:
      type: object
      required:
      - hospitDevelopal      
      - demands
      - contact
      - releaseDate
      - validation
      properties:
        id:
          type: string
          format: uuid
          example: d290f1ee-6c54-4b01-90e6-d701748f0851
        hospital:
          $ref: 'hospitals.yaml#/components/schemas/HospitalItem'

        validation:
          $ref: 'validations.yaml#/components/schemas/ValidationItem'
        releaseDate:
          type: string
          format: date-time
          example: 2016-08-29T09:12:33.001Z
        contact:
          $ref: 'validations.yaml#/components/schemas/Contact'
        demands:
          type: array
          items:
              type: object
              required:
              - supply
              properties:
                supply:
                  $ref: 'supplies.yaml#/components/schemas/SupplyItem'
                amount:
                  oneOf:
                    - type: integer
                      format: int32
                      description: 个
                    - $ref: 'suppliesunits.yaml#/components/schemas/SupplyItemUnit'
                    - $ref: 'suppliesunits.yaml#/components/schemas/Unit'
                remark:
                  type: string
                  example: 需符合或高于下列国家标准,医用一次性防护服技术要求
        availableState:
          oneOf:
          - type: boolean
            default: true
          - $ref: 'validations.yaml#/components/schemas/SuspendItem'


================================================
FILE: src/swagger/archived/supplies.yaml
================================================
openapi: 3.0.2
info:
  description: This API provides Supplies list
  version: 0.2.0
  title: Supplies List API
  contact:
    email: wuhan2020@your-company.com
  license:
    name: Apache 2.0
    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
tags:
  - name: contributors
    description: Secured write permission calls
  - name: developers
    description: Operations available to regular developers
paths:
  /supplies:
    get:
      tags:
        - developers
      summary: searches supplies
      operationId: searchSupplies
      description: |
        By passing in the appropriate options, you can search for
        available supplies in the system
      parameters:
        - in: query
          name: searchString
          description: pass an optional search string for looking up supplies
          required: false
          schema:
            type: string
        - in: query
          name: skip
          description: number of records to skip for pagination
          schema:
            type: integer
            format: int32
            minimum: 0
        - in: query
          name: limit
          description: maximum number of records to return
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 50
      responses:
        '200':
          description: search results matching criteria
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SupplyItem'
        '400':
          description: bad input parameter
    post:
      tags:
        - contributors
      summary: adds a supply item
      operationId: addSupply
      description: Adds an item to the system
      responses:
        '201':
          description: item created
        '400':
          description: 'invalid input, object invalid'
        '409':
          description: an existing item already exists
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SupplyItem'
        description: Supply item to add
servers:
  - url: 'https://virtserver.swaggerhub.com/wuhan2020/supplies/0.2.0'
components:
  schemas:
    SupplyItem:
      type: object
      required:
        - id
        - name
        - std
      properties:
        id:
          type: string
          format: uuid
          example: d290f1ee-6c54-4b01-90e6-d701748f0851
        name:
          type: string
          example: 医用口罩
        std:
          type: array
          items:
            $ref: '#/components/schemas/Standard'
        releaseDate:
          type: string
          format: date-time
          example: '2016-08-29T09:12:33.001Z'
    Standard:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          example: GB 19083-2010
        desc:
          type: string
          example: 国家标医用标准

================================================
FILE: src/swagger/archived/suppliesunits.yaml
================================================
openapi: 3.0.2
info:
  description: This API provides Supplies list
  version: 0.2.0
  title: Supplies Units List API
  contact:
    email: wuhan2020@your-company.com
  license:
    name: Apache 2.0
    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
tags:
  - name: contributors
    description: Secured write permission calls
  - name: developers
    description: Operations available to regular developers
paths:
  /suppliesunits:
    get:
      tags:
        - developers
      summary: searches supplies units
      operationId: searchSuppliesUnits
      description: |
        By passing in the appropriate options, you can search for
        available supplies units in the system
      parameters:
        - in: query
          name: searchString
          description: pass an optional search string for looking up inventory
          required: false
          schema:
            type: string
        - in: query
          name: skip
          description: number of records to skip for pagination
          schema:
            type: integer
            format: int32
            minimum: 0
        - in: query
          name: limit
          description: maximum number of records to return
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 50
      responses:
        '200':
          description: search results matching criteria
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SupplyItemUnit'
        '400':
          description: bad input parameter
    post:
      tags:
        - contributors
      summary: adds a supply item
      operationId: addSupply
      description: Adds an item to the system
      responses:
        '201':
          description: item created
        '400':
          description: 'invalid input, object invalid'
        '409':
          description: an existing item already exists
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SupplyItemUnit'
        description: Supply item to add
servers:
  - url: 'https://virtserver.swaggerhub.com/wuhan2020/suppliesunits/0.2.0'
components:
  schemas:
    SupplyItemUnit:
      type: object
      required:
        - id
        - name
        - unitamount
        - volume
      properties:
        id:
          type: string
          format: uuid
          example: d290f1ee-6c54-4b01-90e6-d701748f0851
        name:
          type: string
          example: 箱
        unitamount:
          type: integer
          format: int32
          example: 250
        desc:
          type: string
          example: 1箱口罩250个
        volume: 
          type: object
          required:
            - length
            - height
            - width
          properties:
            length:
              $ref: '#/components/schemas/Length'
            height:
              $ref: '#/components/schemas/Length'
            width:
              $ref: '#/components/schemas/Length'
        weight:
          $ref: '#/components/schemas/Weight'
        releaseDate:
          type: string
          format: date-time
          example: '2016-08-29T09:12:33.001Z'
    Unit:
      oneOf:
        - $ref: '#/components/schemas/Length'
        - $ref: '#/components/schemas/Size'
        - $ref: '#/components/schemas/Weight'
        - $ref: '#/components/schemas/Volume'
    Size:
      type: object
      required:
        - amount
        - unit
      properties:
        amount: 
          type: integer
          format: int32
        unit:
          type: string
          enum: ['#']
          description: 号
    Length:      
      type: object
      required:
        - amount
        - unit
      properties:
        amount: 
          type: number
          format: float
        unit:
          type: string
          enum: [CM, M]
          description: 米, 厘米
    Weight:
      type: object
      required:
        - amount
        - unit
      properties:
        amount: 
          type: number
          format: float
        unit:
          type: string
          enum: [g, kg, ton]
          description: 克, 千克, 吨
    Volume:
      type: object
      required:
        - amount
        - unit
      properties:
        amount: 
          type: number
          format: float
        unit:
          type: string
          enum: [ml, L]
          description: 毫升,升

================================================
FILE: src/swagger/errors.yml
================================================
# This YML defines the Error Response
# for most of the errors
components:
  # 500
  InternalServerError:
    description: The server cannot process the request for an unknown reason
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/Error"
  # 400
  BadRequest:
    description: The HTTP request that was sent to the server has invalid syntax
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/Error"
  # 404
  NotFound:
    description: The specified resource was not found
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/Error"
  # 401
  Unauthorized:
    description: Unauthorized
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/Error"
  schemas:
    Error:
      type: object
      properties:
        code:
          type: string
        message:
          type: string
          example: "Error message shows here."
      required:
        - message


================================================
FILE: src/swagger/hospitals.yml
================================================
paths:
  /hospital/all:
    get:
      tags:
        - Wuhan2020 Data
      summary: Search for all available hospitals
      operationId: src.api.hospitals.get_all
      description: |
        By passing in the appropriate options, 
        you can get all of the available hospitals
        or query for specific hospitals in the system
      parameters:
        - in: query
          name: skip
          description: number of records to skip for pagination
          schema:
            type: integer
            format: int32
            minimum: 0
            default: 0
        - in: query
          name: limit
          description: maximum number of records to return
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 50
            default: 50
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/HospitalItem"
        "400":
          $ref: "errors.yml#/components/BadRequest"
        "500":
          $ref: "errors.yml#/components/InternalServerError"
        # Definition of all other error statuses
        default:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: "errors.yml#/components/schemas/Error"

components:
  schemas:
    HospitalItem:
      type: object
      required:
        - id
        - name
        - city
        - address
        - releaseDate
      properties:
        id:
          type: string
          format: uuid
          example: d290f1ee-6c54-4b01-90e6-d701748f0851
        name:
          type: string
          example: 武汉第一人民医院
        city:
          type: string
          example: 武汉市
        address:
          type: string
          example: 湖北省武汉市东湖路169号 武汉大学中南医院
        releaseDate:
          type: string
          format: date-time
          example: "2016-08-29T09:12:33.001Z"


================================================
FILE: src/swagger/validations.yaml
================================================
openapi: 3.0.2
info:
  description: This API provides Base Validation Item list and validation feature
  version: 0.1.0
  title: Validation API
  contact:
    email: wuhan2020@your-company.com
  license:
    name: Apache 2.0
    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
tags:
  - name: contributors
    description: Secured write permission calls
  - name: reviewers
    description: Secured write 'reviewState' field permission update calls
  - name: developers
    description: Operations available to regular developers
paths:
  /validations:
    get:
      tags:
        - developers
      summary: searches validations
      operationId: searchValidations
      description: |
        By passing in the appropriate options, you can search for
        existing validations in the system
      parameters:
        - in: query
          name: searchString
          description: pass an optional search string for looking up validations
          required: false
          schema:
            type: string
        - in: query
          name: skip
          description: number of records to skip for pagination
          schema:
            type: integer
            format: int32
            minimum: 0
        - in: query
          name: limit
          description: maximum number of records to return
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 50
      responses:
        '200':
          description: search results matching criteria
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ValidationItem'
        '400':
          description: bad input parameter
    post:
      tags:
        - contributors
      summary: adds a accomodation item
      operationId: addValidation
      description: Adds an item to the system
      responses:
        '201':
          description: item created
        '400':
          description: 'invalid input, object invalid'
        '409':
          description: an existing item already exists
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ValidationItem'
        description: Validation item to add
    put:
      tags:
        - reviewers
      summary: adds a accomodation item
      operationId: updateValidation
      description: Update an item with 'approved' status the system
      responses:
        '201':
          description: 'item updated'
        '400':
          description: 'invalid input, object invalid'
        '403':
          description: 'forbidden'
        '404':
          description: 'item not found'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ValidationItem'
        description: Validation item to add
servers:
  - url: 'https://virtserver.swaggerhub.com/wuhan2020/validations/0.1.0'
components:
  schemas:
    ValidationItem:
      type: object
      required:
        - id
        - url
        - name
        - source
        - sourcetype
        - releaseDate
      properties:
        id:
          type: string
          format: uuid
          example: d290f1ee-6c54-4b01-90e6-d701748f0851
        url:
          type: string
          format: uri
          example: https://paper.people.com.cn
        name:
          type: string
          example: 湖北紧急求援
        source:
          type: string
          example: 人民日报海外版
        sourcetype:
          type: string
          enum: ['hospitaldemand','patientreport','logistic','accommodation','supplies','general']
        releaseDate:
          type: string
          format: date-time
          example: '2016-08-29T09:12:33.001Z'
        contributor:
          $ref: '#/components/schemas/Operator'
        reviewStates:
          type: array
          items:
            $ref: '#/components/schemas/ReviewState'
    Operator:
      type: object
      required:
        - id
        - username
      properties:
        id:
          type: string
          format: uuid
          example: d290f1ee-6c54-4b01-90e6-d701748f0851        
        username:
          type: string
          example: 我的网名是柱子
        email:
          type: string
          format: email        
    ReviewState:
      type: object
      required:
        - status
        - reviewDate
      properties:
        status:
          type: string
          enum: ['truth','uncertain','false']
          example: 已验证为真实 truth
          default: 'uncertain'
        reviewDate:
          type: string
          format: date-time
          example: '2016-08-29T09:12:33.001Z'
        reviewer:
          $ref: '#/components/schemas/Operator'    
    Contact:
      type: object
      required:
        - name
        - phone
      properties:
        name:
          type: string
          example: 王老师,李经理
        phone:
          type: array
          items:
            type: string
            example: 21-221111111
        email:
          type: string
          example: example@163.com
    SuspendItem:
      type: object
      required:
        - id
        - reason
        - validation
        - suspendDate
      properties:
        id:
          type: string
          format: uuid
          example: d290f1ee-6c54-4b01-90e6-d701748f0851
          description: 应取消的项目的id,例如医院需求id        
        reason:
          oneOf:
           - type: string
             enum: ['已过时','判定不真实','已撤销','已完成','已结束']
           - type: object
             properties:
               desc:
                 type: string
                 example: 外界不可抗力
        validation:
          $ref: '#/components/schemas/ValidationItem'
        suspendDate:
          type: string
          format: date-time
          example: '2016-08-29T09:12:33.001Z'

================================================
FILE: src/tests/__init__.py
================================================


================================================
FILE: src/tests/data/csv/DONATION.csv
================================================
¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,
,տʽ,ٷ,տ˻,ǰ״̬,״̬,
ƱУѻ,пת,https://mp.weixin.qq.com/s/dXed5MIYgBisrV_pfQmV0w,"˻
xx
Уйб山·֧
˺ţxxxxx
˻ΪУѻ˻",,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,


================================================
FILE: src/tests/data/csv/FACTORY.csv
================================================
¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
ʾд,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,沿,,Ʒ,,,,,Ȳ,,,IJ,,,,,IJ,,豸,,,֤,̵ַ,ϵʽ,ע,ϢԴ,״̬,
,,ͨҽÿ,ҽƿ,ҽ÷ | N95,/Ŀ/۾,,ñ/ҽñ/Բñ,,,,齺,ͲЬ/Ⱦѥ,ȾЬ,Ⱦѥ,84Һ,,75%ƾ,ֲƤҺ,,,ҽʽ,豸,豸,ҽ,,,,,,,
׼/ƼƷ,,YY/T 0969-2013,YY 0469-2010,"GB 19083-2010, 3M 1860/1870/9123,ĭѪҺҺ",,,,,GB 19082-2003,,GB 10213-2006,,,,,,,,,,,,ҽеע֤,ҽеע֤,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
ɶнţ,ĴƼ޹˾,һҽÿ,,,,,,,,,,,,,,,,,,,,,,,,ĴʡɶйҵӶ·39,,,http://finance.sina.com.cn/wm/2020-01-26/doc-iihnzahk6405080.shtml,,Ǿ
,ҽƷ޹˾,,ҽƷ֣2000ֻ,ҽ÷N95100ֻ,,,,,ҽһԷ10,,,,,,,,,,,,,,,,,й.ɽʡ·153,,ϵˣ꣨,http://finance.sina.com.cn/wm/2020-01-26/doc-iihnzahk6405080.shtml,,Ǿ
Ϻ,Ϻ֮ҽҩƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20203400057,Ϻ¿·58826¥1¥107Һ102,,͹״2019-nCoVԼУӫPCR,http://dy.163.com/v2/article/detail/F3GCB07P0530JPJ4.html,,
Ϻ,ϺҽƿƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,е20180202,ϺֶƼ·908Ū18¥3¥,,Լ,http://dy.163.com/v2/article/detail/F3GCB07P0530JPJ4.html,,
Ϻ,ϺƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,,Ϻмζ·137862279,,Լ,http://huiruibio.com/contact.asp,,
,ȵƼ()޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20163401400,кҵ·36509510,,ʵʱӫⶨPCR,https://baijiahao.baidu.com/s?id=1656405518294494200&wfr=spider&for=pc,,
ʡɳ,ʥƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,泤е20150021,ɳ¼ҵ´·680,,Լ,https://baijiahao.baidu.com/s?id=1656405518294494200&wfr=spider&for=pc,,
ʡ̩,˶Ƽ޹˾,,,,,,,,,,,,,,,,,,,,,,,,̩е20150182,ʡ̩п︻Ұ,,Լ,https://baijiahao.baidu.com/s?id=1656405518294494200&wfr=spider&for=pc,,
Ϻ,ϺŵƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20203400058,Ϻ·466¥,,͹״2019-nCoVԼУӫPCR,https://baijiahao.baidu.com/s?id=1656405518294494200&wfr=spider&for=pc,,
人,Ƽ人޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20203400060,人ж¼´666人ҵĿBCDз¥B2¥B1һ¥,,͹״2019-nCoVԼУӫPCR,https://baijiahao.baidu.com/s?id=1656405518294494200&wfr=spider&for=pc,,
,ݰ˼ҽѧƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20153400667,·320һ,,ʵʱӫⶨPCR,,,
ʡ,¡Ƽ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20153400710,оü·389,,ʵʱӫⶨPCR,,,
,̩ѧй޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20183401609,ͬ·2041101201301Ԫ2045101201501Ԫ,,ʵʱӫⶨPCR,,,
,ݰԴ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20183400126,ݸƼǽ·81¥41815¥103220311,,ʵʱӫⶨPCR,,,
,ɽѧﰲɷ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20183401526,и¼ҵɽ·19,,ʵʱӫⶨPCR,,,
ʡկ,ͬƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20183400129,ʡկִҵ԰ͩҵ԰A7¥1¥2¥,,ʵʱӫⶨPCR,,,
,\޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20173401410,ݹҵ԰Ǻ218׿Ƽ԰C7¥101201,,ʵʱӫⶨPCR,,,
,ŵ\޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20153400948,бü·192405407408,,ʵʱӫⶨPCR,,,
,ݵϰ\޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20193220321,㽭ʡຼǰֵ·115㡢1¥4423,,ʵʱӫⶨPCR,,,
,ݲտƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20193220680,и¼ҵ·1192,,ʵʱӫⶨPCR,,,


================================================
FILE: src/tests/data/csv/HOSPITAL.csv
================================================
ҪֱдûҪֱ1ûдκϢ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,沿,,Ʒ,,,,,Ȳ,,,IJ,,,,,IJ,,豸,,,ٷ,ҽԺַ,ϵʽ,ע,״̬,,,
,,ͨҽÿ,ҽƿ,ҽ÷ | N95,/Ŀ/۾,,ñ/ҽñ/Բñ,,,,齺,ͲЬ/Ⱦѥ,ȾЬ,Ⱦѥ,84Һ,,75%ƾ,ֲƤҺ,,,ҽʽ,豸,豸,ҽ,,,,,,,,
׼/ƼƷ,,YY/T 0969-2013,YY 0469-2010,"GB 19083-2010, 3M 1860/1870/9123,ĭѪҺҺ",,,,,GB 19082-2003,,GB 10213-2006,,,,,,,,,,,,ҽеע֤,ҽеע֤,,,,,,,,
,ҽԺ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,еڶҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,https://mp.weixin.qq.com/s/EmDnJVak0MQ0W0N9aRbfHw,ɳ·241,,,,,"ǵλٷϢ, Ϊ԰, Ӧɿ",2020.01.27
,еһҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,http://www.jzyy1949.com/user_queryArticleById?article.aid=9726,ɳ·8 еһҽԺе,,,,,"ǵλٷϢ, Ϊ԰, Ӧɿ",2020.01.27
,ҽԺ,1,YY 0469-2011,1,1,1,1,,1,,,,,,,,,,,,,,,,https://mp.weixin.qq.com/s/EmDnJVak0MQ0W0N9aRbfHw,о·60 ҽԺĿ,,,,,"ǵλٷϢ, Ϊ԰, Ӧɿ",2020.01.27
,ؿҽԺ,,,,,,,,,,,,,,,,,,,,,,,,https://mp.weixin.qq.com/s/EmDnJVak0MQ0W0N9aRbfHw,ʡо·6,,,,,"ǵλٷϢ, Ϊ԰, Ӧɿ",2020.01.27
,еҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,https://mp.weixin.qq.com/s/EmDnJVak0MQ0W0N9aRbfHw,б·196,,,,,"ǵλٷϢ, Ϊ԰, Ӧɿ",2020.01.27
,кʮֻ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,http://www.jingzhou.gov.cn/zfwxw/jzyq/202001/t20200125_451837.shtml,غʮֻ/ܻͳһ,,,,,,
,ҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,,нغѨ29,,ݲ޹صʺ;,,,https://weibo.com/u/6989496719?refer_flag=1005055013_&is_all=1,
,ؿҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,,о6,,,,,,
,иױԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,,ʡо·233,,,,,,
,мҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,,ʡݳ344,,,,,,
,ҽԺ,,,,,,,,,,,,,,,,,,,,,,,,,½152,,,,,,
,ҽҽԺ,,,,,,,,,,,,,,,,,,,,,,,,,кִ·㴦,,޹棬ž http://news.jznews.com.cn/system/2020/01/26/011980374.shtml,,,,
,ҽҽԺ,,,,,,,,,,,,,,,,,,,,,,,,,ʡкȪ·6,,޹棬ž http://news.jznews.com.cn/system/2020/01/26/011980374.shtml,,,,
ʯ,ʯкʮֻ,1,1,1,1,1,1,1,1,1,1,,1,,1,1,1,,,,,,,,,,,ݲ޹صʺ;޹棬ž http://news.jznews.com.cn/system/2020/01/26/011980374.shtml,,,,
,ҽҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,http://www.jzszyyy.com/z/yiyuandongtai/yiyuanxinwen/2020-01-25/1777.html,ʡҽҽԺ 豸ҽԺַн·172,,,,,,
,йҽԺ,,,,,,,,,,,,,,,,,,,,,,,,,й119,,2020-1-27,,,,
ʯ,ʯҽԺ,1,"YY 0469-2011
5000",2000,3000,1,3000,1000,2000,1,5000,,1000,,1,1,1,,,,,,,,https://mp.weixin.qq.com/s?__biz=MzU2Mzg1MzE5NA==&mid=2247486061&idx=1&sn=b92e03436c18c9ad12a6649a65ead2c3&chksm=fc52a888cb25219e93199201443fc69cd1e736afaa0cba932c12d73925a61c8dcb77a8be3bb7&mpshare=1&scene=1&srcid=&sharer_sharetime=1580280881992&sharer_shareid=5358617ddd2b35735212b40f5eac5301&key=3e858514d2c9d9aa83685104fbf96d3d0d178a06b862aa2a2c3bdecda704ff1ec2d68a213ec57fd19ec19ac168baf5abab36a561d40268957da0f45694a3d7c2de1f69dc6842433bb1ea4ad5caf980a3&ascene=1&uin=MTA5Nzg3NjQ4Mw%3D%3D&devicetype=Windows+10&version=6208006f?=zh_CN&exportkey=AdBnr5Dtk0s1m7%2FPWI3GaKE%3D&pass_ticket=YBuiHNZN%2Fqi2HS0PznCVi0YbW4jODt18BrmF3xRXH8jk2IXOe03FrxoDnP2j%2Bf3Y,ʡʯŶ·㴦,,2020-1-27,,,ٷϢѾ绰ȷ,


================================================
FILE: src/tests/data/csv/HOTEL.csv
================================================
¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,,,,,
Ƶ,ƵϽ,Ƶַ,?Ƶṩ,ƵɽӴ,ϵ,ϵʽ,ע,ϢԴ,״̬,
ƵƸѨ,Ѩ,·,,,,,,https://m.traveldaily.cn/article/135333?scene=1&clicktime=1580130420&enterid=1580130420&from=singlemessage&isappinstalled=0,,
бѨվ,Ѩ,188,,,,,,https://mp.weixin.qq.com/s/VuCa0DdBtw8vqgxb6P1xGA,,
бѨ㳡,,ڴ99,,,,,,,,
бϵ,,ɽǴ2,,,,,,,,
бݺ찲㳡,찲,ʹ㳡Ա,,,,,,,,


================================================
FILE: src/tests/data/csv/LOGISTICAL.csv
================================================
¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,,,,,,,,,,,,,
,,ϵʽ,,ע,״̬,,Ԯ,,,,,,,,,,,
˳Ἧ,人ij,95338,https://mp.weixin.qq.com/s/42UEPYlYR1EDCM8JKZQyqw,,,,,,,,,,,,,,,
,人,950616,https://mp.weixin.qq.com/s/5ZYvBOFSDdh3-AYFU7wzAQ,ܸ˾,,,,,,,,,,,,,,
°,人,13917258981;18043320078,https://mp.weixin.qq.com/s/xCGmBHEOrgwfFDobjigHKQ,ܸ˾,,,,,,,,,,,,,,
,人,400-900-5656,https://tech.sina.com.cn/i/2020-01-25/doc-iihnzahk6300507.shtml,,,,,,,,,,,,,,,
Բͨٵ޹˾,人,95554,http://www.yto.net.cn/about/news/ytonews/detail.html/?id=7c257cc4-1291-4eba-9aeb-10414f389e88,ܸ˾,,,,,,,,,,,,,,
ͨݼ,人,95311,https://www.zto.com/companyIntroduce/newsListDetail.html?id=1267040,ܸ˾,,,,,,,,,,,,,,
ӿ,人,4000565666,https://mp.weixin.qq.com/s/D9orpDHGp2xJT1V8pIbSYw,ܸ˾,,,,,,,,,,,,,,
˳,人,4008009999,https://weibo.com/2780826007/IrfwsAo3m?type=repost#_rnd1580099824814,,,,人ѧҽԺҽԺвսҽԺɽСɽҽԺ人ܱ,ɽɶϡ人,,,,,,,,,,
غ,人,15915803827,https://weibo.com/2780826007/IrffCjDCa?from=page_1002062780826007_profile&wvr=6&mod=weibotime&type=comment#_rnd1580114854609,,,,,,,,,,,,,,,
,人,10103636/appͷ,https://weibo.com/2780826007/IreEZaTrw?from=page_1002062780826007_profile&wvr=6&mod=weibotime&type=comment#_rnd1580114913374,,,,,,,,,,,,,,,
й,人,11183,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,,,,,,,,,,,,,,,
ϴٵ,人,95546,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,
,人,051-56267288ֻ83424,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,
,人,95344,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,
,人,95315,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,˾󣬽뵱Ż֯ϵ,,,,,,,,,,,,,,
,人,95006,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,
,人,400-866-5566,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾Խӣվֻ19906791226 2ִתȷ񣺴13967130612 18601625459,,,,,,,,,,,,,,
Խ,人,95324/18923876321,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,
լ,人,01053265090/ 13501275106,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,
ػ,,400-808-6666,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,
,人,"  17379175656/
  18784733363/  18010017622/  18629291855/  18863932588/  13801500174",https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,
Ҽ׵δ,人,95058,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,˾󣬽뵱Ż֯ϵ,,,,,,,,,,,,,,
ٿ,人,95349,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,˾󣬽뵱Ż֯ϵ,,,,,,,,,,,,,,
칷,人,"4008909009ͷʱ125-27Ϊ9:00-18:00,128պΪ8:00-20:00)",https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ϵ人ؽշϵ칷,,,,,,,,,,,,,,
,人,⽭֣ 18017713330/? 13916478826򱱳֣? 18911773800ɶ֣? 15208319985,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ҽƷʿɼ뷢⽭֡򱱳֡ϳɶ֣ڼв⼰ڲѡ,,,,,,,,,,,,,,
׼ʱ﹩Ӧ,ī硢ձԽϡĴǡ̩ǡӡǡ¼¡ɱӡȡ̨ۡ,׼ʱɫͨߣ400 189 8868 䣺jusda-callcenter@jusdascm.com,https://weibo.com/2780826007/IrrjhFjaE,ݲΪṩɫ֧ͨ,,ӱ,,,,,,,,,,,,
GOOD,ɼLos Angelesֿ/ŦԼNew Yorkֿ/˰Oregonֿ,"ϵˣBryan ϵ绰6262976863ɼֿ 17421 East Gale Ave Unit C,City of Industry CA91748 / ŦԼֿ⣺75 Glendale Ave Edison NJ08817 / ˰ݲֿ 7021 NE 79th Court Portland OR97218",https://mp.weixin.qq.com/s/PB_-X4HxjTKHbdVcIEwksw,עһ1.װ豸ע2. 豸עҪջϢ 3. 豸עڼƷƷ,,ӱ,,,,http://www.goodkuaidi.com/NewsDetail?GID=da62467c-102e-4b8d-b73d-0916c0df7489,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,


================================================
FILE: src/tests/data/test.json
================================================
{"code":0,"data":{},"msg":"success"}


================================================
FILE: src/tests/data/test.xml
================================================
<data>
    <code>0</code>
    <msg>success</msg>
    <data>

    </data>

</data>


================================================
FILE: src/tests/test_nothing.py
================================================
def test_nothing():
    """Placeholder for Pytest on Github Actions."""
    assert True


================================================
FILE: src/utils/__init__.py
================================================


================================================
FILE: tools.py
================================================
import os
import yaml
import xmltodict
import json
import functools
import logging
from flask import abort
from flask_httpauth import HTTPTokenAuth

from config.settings import DEBUG_FLAG

# TODO: use .gitignore hide token; i don't know how to use this auth in blueprint
auth = HTTPTokenAuth(scheme='Bearer')
test_token = 'test-safe-wuhan'
auth_file = os.path.join(os.path.abspath(__file__), 'auth/auth_info.json')
auth_token = test_token if DEBUG_FLAG else json.load(auth_file)['token']


@auth.verify_token
def auth_token_wrapper(token):
    if token == auth_token:
        return True
    return False


def csv_helper(fpath, headers):
    header_st = 2
    result = []
    with open(fpath) as f:
        for line in f.readlines()[2:]:
            csv_data = line.strip().split(",")
            result.append(dict(zip(headers, csv_data)))
    return result


def csv_with_medical_supplier(fpath, headers):
    header_st, spliter = 5, '#'
    result, total_header = [], []
    for h in headers:
        if isinstance(h, list):
            for sub_h in h:
                total_header.append(spliter.join(sub_h))
        else:
            total_header.append(h)
    with open(fpath) as f:
        for line in f.readlines()[header_st:]:
            csv_data = line.strip().split(",")
            result.append(dict(zip(total_header, csv_data)))
    return result


def yaml_helper(fpath):
    result = []
    with open(fpath, 'r') as f:
        result = yaml.load(f)
    return result


def xml_helper(xml_path):
    with open(xml_path, 'r') as f:
        xml_str = f.read()
    json = xmltodict.parse(xml_str)
    return json


def json_helper(json_path):
    with open(json_path, 'r', encoding='UTF-8') as f:
        return json.loads(f.read())


================================================
FILE: utils.py
================================================
# -*- coding: utf-8 -*-
from flask import Blueprint, current_app, request
import os
import json
import datetime
import platform
import csv
import os
import traceback
import yaml
import xmltodict
import json

from const import *
from tools import *

data = Blueprint('register', __name__)


@data.route('/json_test')
def json_test():
    path = os.path.join("/root/api-server/", "test.json")
    return json_helper(path)


@data.route('/xml_test')
def xml_test():
    path = os.path.join("/root/api-server/", "test.xml")
    return xml_helper(path)


@data.route('/hospital_list')
def hospital_list():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        hosptials_data = csv_with_medical_supplier(current_app.config['HOSPITAL_PATH'], HOSPITAL_HEADERS)
        if 'limit' in request.args or 'skip' in request.args:
            skip = request.args.get('skip', type=int)
            limit = request.args.get('limit', type=int)
            hosptials_data_len = len(hosptials_data)
            if skip < 0 or limit < 0 or limit > 50:
                raise Exception('Bad input parameter.')
            if skip > hosptials_data_len:
                raise Exception("Index out of range.")
            if skip + limit > hosptials_data_len:
                limit = hosptials_data_len - skip
            resp['data'] = hosptials_data[skip:skip+limit]
        else:
            resp['data'] = hosptials_data
        resp['success'] = True
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False),(400 if not resp['success'] else 200)


@data.route('/hotel_list')
@auth.login_required
def hotel_list():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = csv_helper(current_app.config['HOTEL_PATH'], HOTEL_HEADERS)
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)


@data.route('/logistical_list')
@auth.login_required
def logistical_list():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = csv_with_medical_supplier(current_app.config['LOGISITICAL_PATH'], LOGISTICS_HEADERS)
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)


@data.route('/news_list')
@auth.login_required
def news_list():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = csv_helper(current_app.config['NEWS_PATH'], NEWS_HEADERS)
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)


@data.route('/donation_list')
@auth.login_required
def donation_list():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = csv_helper(current_app.config['DONATION_PATH'], DONATION_HEADERS)
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)


@data.route('/factory_list')
@auth.login_required
def factory_list():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = csv_with_medical_supplier(current_app.config['FACTORY_PATH'], FACTORY_HEADERS)
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)


@data.route('/clinic_list')
@auth.login_required
def clinic_list():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = csv_helper(current_app.config['CLINIC_PATH'], CLINIC_HEADERS)
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)

@data.route('/hospital_list_json')
def hospital_list_json():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data= json_helper(current_app.config['JSON_HOSPITAL_PATH'])
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)




@data.route('/hotel_list_json')
def hotel_list_json():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = json_helper(current_app.config['JSON_HOTEL_PATH'])
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)


@data.route('/logstics_list_json')
def logstics_list_json():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = json_helper(current_app.config['JSON_LOGISITICAL_PATH'])
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)


@data.route('/news_list_json')
def news_list_json():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = json_helper(current_app.config['JSON_NEWS_PATH'])
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)


@data.route('/donation_list_json')
def donation_list_json():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = json_helper(current_app.config['JSON_DONATION_PATH'])
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)


@data.route('/factory_list_json')
def factory_list_json():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = json_helper(current_app.config['JSON_FACTORY_PATH'])
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)


@data.route('/clinic_list_json')
def clinic_list_json():
    resp = {
        'success': False,
        'data': [],
        'msg': '',
    }
    try:
        resp_data = json_helper(current_app.config['JSON_CLINIC_PATH'])
        resp['success'] = True
        resp['data'] = resp_data
    except Exception as e:
        resp['msg'] = str(e)
    return json.dumps(resp, ensure_ascii=False)
Download .txt
gitextract_rth757f3/

├── .dockerignore
├── .github/
│   ├── hypertrons.json
│   ├── pull_request_template.md
│   └── workflows/
│       └── pythonapp.yml
├── .gitignore
├── .gitmodules
├── .python-version
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README-cn.md
├── README.md
├── bootstrap
├── config/
│   ├── dev.py
│   ├── product.py
│   └── settings.py
├── const.py
├── requirements.txt
├── src/
│   ├── __init__.py
│   ├── api/
│   │   ├── __init__.py
│   │   ├── accommodations.py
│   │   └── hospitals.py
│   ├── core/
│   │   └── __init__.py
│   ├── main.py
│   ├── swagger/
│   │   ├── accommodations.yml
│   │   ├── api.yml
│   │   ├── archived/
│   │   │   ├── accomodation.yaml
│   │   │   ├── donation.yaml
│   │   │   ├── hospitaldemands.yaml
│   │   │   ├── supplies.yaml
│   │   │   └── suppliesunits.yaml
│   │   ├── errors.yml
│   │   ├── hospitals.yml
│   │   └── validations.yaml
│   ├── tests/
│   │   ├── __init__.py
│   │   ├── data/
│   │   │   ├── csv/
│   │   │   │   ├── DONATION.csv
│   │   │   │   ├── FACTORY.csv
│   │   │   │   ├── HOSPITAL.csv
│   │   │   │   ├── HOTEL.csv
│   │   │   │   └── LOGISTICAL.csv
│   │   │   ├── test.json
│   │   │   └── test.xml
│   │   └── test_nothing.py
│   └── utils/
│       └── __init__.py
├── tools.py
└── utils.py
Download .txt
SYMBOL INDEX (32 symbols across 7 files)

FILE: config/settings.py
  function get_cache_path (line 6) | def get_cache_path():
  class Config (line 19) | class Config(object):
  class CacheCfg (line 27) | class CacheCfg(Config):

FILE: src/api/accommodations.py
  function get_all (line 1) | def get_all():
  function get_by_name (line 6) | def get_by_name():

FILE: src/api/hospitals.py
  function get_all (line 1) | def get_all():
  function add (line 6) | def add():

FILE: src/main.py
  function aggregate_specs (line 20) | def aggregate_specs(main_file: Path) -> Dict[str, Any]:
  function handler (line 45) | def handler(environ, start_response) -> flask.Flask:

FILE: src/tests/test_nothing.py
  function test_nothing (line 1) | def test_nothing():

FILE: tools.py
  function auth_token_wrapper (line 20) | def auth_token_wrapper(token):
  function csv_helper (line 26) | def csv_helper(fpath, headers):
  function csv_with_medical_supplier (line 36) | def csv_with_medical_supplier(fpath, headers):
  function yaml_helper (line 52) | def yaml_helper(fpath):
  function xml_helper (line 59) | def xml_helper(xml_path):
  function json_helper (line 66) | def json_helper(json_path):

FILE: utils.py
  function json_test (line 21) | def json_test():
  function xml_test (line 27) | def xml_test():
  function hospital_list (line 33) | def hospital_list():
  function hotel_list (line 62) | def hotel_list():
  function logistical_list (line 79) | def logistical_list():
  function news_list (line 96) | def news_list():
  function donation_list (line 113) | def donation_list():
  function factory_list (line 130) | def factory_list():
  function clinic_list (line 147) | def clinic_list():
  function hospital_list_json (line 162) | def hospital_list_json():
  function hotel_list_json (line 180) | def hotel_list_json():
  function logstics_list_json (line 196) | def logstics_list_json():
  function news_list_json (line 212) | def news_list_json():
  function donation_list_json (line 228) | def donation_list_json():
  function factory_list_json (line 244) | def factory_list_json():
  function clinic_list_json (line 260) | def clinic_list_json():
Condensed preview — 46 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (82K chars).
[
  {
    "path": ".dockerignore",
    "chars": 39,
    "preview": "README.md\nREADME-en.md\nCONTRIBUTING.md\n"
  },
  {
    "path": ".github/hypertrons.json",
    "chars": 1808,
    "preview": "{\n  \"label_setup\": {\n    \"version\": 1,\n    \"labels\": [\n      {\n        \"__merge__\": true\n      },\n      {\n        \"name\""
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 389,
    "preview": "### Purpose | 本PR解决的问题\n<!-- Please include the GitHub issue this fixes or resolves, if applicable, please also explain a"
  },
  {
    "path": ".github/workflows/pythonapp.yml",
    "chars": 949,
    "preview": "name: Tests on Pull Requests and Master\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n\njobs:\n  build:\n    ru"
  },
  {
    "path": ".gitignore",
    "chars": 145,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n*.pyc\n__pycache__/\n.vscode/\n.idea/"
  },
  {
    "path": ".gitmodules",
    "chars": 88,
    "preview": "[submodule \"wuhan2020\"]\n\tpath = wuhan2020\n\turl = git@github.com:wuhan2020/wuhan2020.git\n"
  },
  {
    "path": ".python-version",
    "chars": 7,
    "preview": "3.6.10\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2670,
    "preview": "# Contributing Guide\n\n## Structure\n\n![Tech Arch Diagram](https://www.lucidchart.com/publicSegments/view/6ab27659-257a-44"
  },
  {
    "path": "Dockerfile",
    "chars": 311,
    "preview": "# Align with the CI/CD YML\n# We cannot use alpine since\n# we need to call bash in entrypoint\nFROM python:3.6\n\n# Setup wo"
  },
  {
    "path": "LICENSE",
    "chars": 1061,
    "preview": "MIT License\n\nCopyright (c) 2020 援助武汉\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof th"
  },
  {
    "path": "README-cn.md",
    "chars": 1936,
    "preview": "# API Server\n\n![Python3.6](https://img.shields.io/badge/python-3.6-green.svg?style=flat-square&logo=python&colorB=blue)\n"
  },
  {
    "path": "README.md",
    "chars": 3013,
    "preview": "# API Server\n\n![Python3.6](https://img.shields.io/badge/python-3.6-green.svg?style=flat-square&logo=python&colorB=blue)\n"
  },
  {
    "path": "bootstrap",
    "chars": 34,
    "preview": "#!/bin/bash\npython3 -m \"src.main\"\n"
  },
  {
    "path": "config/dev.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "config/product.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "config/settings.py",
    "chars": 1578,
    "preview": "import os, sys\n\nDEBUG_FLAG = True\n\n\ndef get_cache_path():\n    path_home = './'\n    if DEBUG_FLAG:\n        path_home = os"
  },
  {
    "path": "const.py",
    "chars": 2095,
    "preview": "\"\"\"\nSUB HEADERS\nTODO: change to en\n\"\"\"\nfactory_medical_supplies = [\n    # 口罩\n    ('普通医用口罩', 'YY/T 0969-2013'),\n    ('医用外"
  },
  {
    "path": "requirements.txt",
    "chars": 131,
    "preview": "Flask==1.1.1\nPyYAML==5.3\nflask-swagger==0.2.14\nxmltodict==0.12.0\nFlask-HTTPAuth==3.3.0\nconnexion[swagger-ui]==2.6.0\npran"
  },
  {
    "path": "src/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/api/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/api/accommodations.py",
    "chars": 138,
    "preview": "def get_all():\n    \"\"\"List all available accomodations.\"\"\"\n    return {}\n\n\ndef get_by_name():\n    \"\"\"Search for accomoda"
  },
  {
    "path": "src/api/hospitals.py",
    "chars": 125,
    "preview": "def get_all():\n    \"\"\"List all available hospitals.\"\"\"\n    return {}\n\n\ndef add():\n    \"\"\"Add new hospitals.\"\"\"\n    retur"
  },
  {
    "path": "src/core/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/main.py",
    "chars": 1739,
    "preview": "import argparse\nimport flask\nfrom flask import Flask\nfrom flask import Response as ResponseBase\nimport connexion\nfrom sw"
  },
  {
    "path": "src/swagger/accommodations.yml",
    "chars": 3728,
    "preview": "paths:\n  /accommodation/all:\n    get:\n      tags:\n        - Wuhan2020 Data\n      summary: Search for all available accom"
  },
  {
    "path": "src/swagger/api.yml",
    "chars": 983,
    "preview": "openapi: 3.0.2\ninfo:\n  title: Wuhan2020 API service\n  description: This is the API service of the Wuhan2020 project, whi"
  },
  {
    "path": "src/swagger/archived/accomodation.yaml",
    "chars": 5037,
    "preview": "openapi: 3.0.2\ninfo:\n  description: This API provides Hotel/motel/ Accomodation list\n  version: 0.1.0\n  title: Accomodat"
  },
  {
    "path": "src/swagger/archived/donation.yaml",
    "chars": 3639,
    "preview": "openapi: 3.0.2\ninfo:\n  description: This API provides Donation list\n  version: 0.2.0\n  title: Donation List API\n  contac"
  },
  {
    "path": "src/swagger/archived/hospitaldemands.yaml",
    "chars": 4478,
    "preview": "openapi: 3.0.2\ninfo:\n  description: This is Hostpital Demands API\n\n  version: 0.2.0\n\n  title: Hostpital Demands API\n  # "
  },
  {
    "path": "src/swagger/archived/supplies.yaml",
    "chars": 2986,
    "preview": "openapi: 3.0.2\ninfo:\n  description: This API provides Supplies list\n  version: 0.2.0\n  title: Supplies List API\n  contac"
  },
  {
    "path": "src/swagger/archived/suppliesunits.yaml",
    "chars": 4521,
    "preview": "openapi: 3.0.2\ninfo:\n  description: This API provides Supplies list\n  version: 0.2.0\n  title: Supplies Units List API\n  "
  },
  {
    "path": "src/swagger/errors.yml",
    "chars": 1023,
    "preview": "# This YML defines the Error Response\n# for most of the errors\ncomponents:\n  # 500\n  InternalServerError:\n    descriptio"
  },
  {
    "path": "src/swagger/hospitals.yml",
    "chars": 2058,
    "preview": "paths:\n  /hospital/all:\n    get:\n      tags:\n        - Wuhan2020 Data\n      summary: Search for all available hospitals\n"
  },
  {
    "path": "src/swagger/validations.yaml",
    "chars": 5907,
    "preview": "openapi: 3.0.2\ninfo:\n  description: This API provides Base Validation Item list and validation feature\n  version: 0.1.0\n"
  },
  {
    "path": "src/tests/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/tests/data/csv/DONATION.csv",
    "chars": 437,
    "preview": "¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,\n,տʽ,ٷ,տ˻,ǰ״̬,״̬,\nƱУѻ,пת,https://mp.weixin.qq.com/s/dXed5MIYgBisrV_pfQmV0w,\"˻\nxx\nУй"
  },
  {
    "path": "src/tests/data/csv/FACTORY.csv",
    "chars": 2413,
    "preview": "¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\nʾд,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\n,,,,,沿,,Ʒ,,,,,Ȳ,,,IJ,,,,,"
  },
  {
    "path": "src/tests/data/csv/HOSPITAL.csv",
    "chars": 2690,
    "preview": "ҪֱдûҪֱ1ûдκϢ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\n,,,,,沿,,Ʒ,,,,,Ȳ,,,IJ,,,,,IJ,,豸,,,ٷ,ҽԺַ,ϵʽ,ע,״̬,,,\n,,ͨҽÿ,ҽƿ,ҽ÷ | N95,/Ŀ/۾,,ñ/ҽñ"
  },
  {
    "path": "src/tests/data/csv/HOTEL.csv",
    "chars": 329,
    "preview": "¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,,,,,\nƵ,ƵϽ,Ƶַ,?Ƶṩ,ƵɽӴ,ϵ,ϵʽ,ע,ϢԴ,״̬,\nƵƸѨ,Ѩ,·,,,,,,https://m.traveldaily.cn/article/135"
  },
  {
    "path": "src/tests/data/csv/LOGISTICAL.csv",
    "chars": 6505,
    "preview": "¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,,,,,,,,,,,,,\n,,ϵʽ,,ע,״̬,,Ԯ,,,,,,,,,,,\n˳Ἧ,人ij,95338,https://mp.weixin.qq.com/s/42UEPYl"
  },
  {
    "path": "src/tests/data/test.json",
    "chars": 37,
    "preview": "{\"code\":0,\"data\":{},\"msg\":\"success\"}\n"
  },
  {
    "path": "src/tests/data/test.xml",
    "chars": 82,
    "preview": "<data>\n    <code>0</code>\n    <msg>success</msg>\n    <data>\n\n    </data>\n\n</data>\n"
  },
  {
    "path": "src/tests/test_nothing.py",
    "chars": 88,
    "preview": "def test_nothing():\n    \"\"\"Placeholder for Pytest on Github Actions.\"\"\"\n    assert True\n"
  },
  {
    "path": "src/utils/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tools.py",
    "chars": 1747,
    "preview": "import os\nimport yaml\nimport xmltodict\nimport json\nimport functools\nimport logging\nfrom flask import abort\nfrom flask_ht"
  },
  {
    "path": "utils.py",
    "chars": 6901,
    "preview": "# -*- coding: utf-8 -*-\nfrom flask import Blueprint, current_app, request\nimport os\nimport json\nimport datetime\nimport p"
  }
]

About this extraction

This page contains the full source code of the wuhan2020/api-server GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 46 files (72.1 KB), approximately 22.8k tokens, and a symbol index with 32 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!