Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

更新行政区域代码201801 #12

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[run]
omit = gb2260/data/*
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ __pycache__
/build
/dist
/htmlcov
/gb2260/data.py
/.idea
/.python-version
.pytest_cache/
gb2260/data/
5 changes: 3 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[submodule "data"]
path = data
url = https://github.com/cn/GB2260.git
path = data
url = https://github.com/cn/GB2260.git
branch = develop
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ python:
- "3.4"
- "pypy"
install:
- "pip install pytest pytest-cov pytest-pep8 coveralls"
- "pip install pytest pytest-cov pytest-pep8 pytest-mock coveralls"
script: "make clean test"
after_success: "coveralls"
branches:
Expand Down
16 changes: 6 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,17 @@ TOX := tox

all: build

build: gb2260/data.py
build: gb2260/data/__init__.py
$(PYTHON) setup.py sdist bdist_wheel

test: gb2260/data.py
test: gb2260/data/__init__.py
$(PYTEST)

test-all: gb2260/data.py
test-all: gb2260/data/__init__.py
$(TOX)

clean:
rm -rf dist build gb2260/data.py
rm -rf dist build gb2260/data/

gb2260/data.py: data/GB2260*.txt
$(PYTHON) generate.py $? $@

data/GB2260*.txt:
git submodule init
git submodule update
gb2260/data/__init__.py: data/revisions.json
$(PYTHON) generate.py $?
2 changes: 1 addition & 1 deletion data
Submodule data updated 118 files
6 changes: 6 additions & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-e.

pytest
pytest-cov
pytest-pep8
pytest-mock
22 changes: 17 additions & 5 deletions gb2260/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
from .division import Division
from __future__ import absolute_import
from __future__ import unicode_literals

__version__ = '0.4.1'
__all__ = ['Division', 'get', 'search']
from gb2260.gb2260 import GB2260
from gb2260.exceptions import (
GB2260Exception,
InvalidCode,
RevisionNotFound,
SourceNotFound,
)

get = Division.get
search = Division.search

__all__ = [
'GB2260',
'GB2260Exception',
'InvalidCode',
'RevisionNotFound',
'SourceNotFound',
]
43 changes: 27 additions & 16 deletions gb2260/_compat.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
from __future__ import absolute_import
from __future__ import unicode_literals

import sys


__all__ = ['PY2', 'unicode_type', 'unicode_compatible']
PY2 = sys.version_info[0] == 2


PY2 = sys.version_info[0] == 2
if PY2:
text_type = unicode
binary_type = str

def iteritems(d):
return d.iteritems()
else:
text_type = str
binary_type = bytes

def iteritems(d):
return d.items()


def unicode_compatible(cls):
if PY2: # pragma: no cover
__str__ = getattr(cls, '__str__', None)
__repr__ = getattr(cls, '__repr__', None)
if __str__ is not None:
cls.__unicode__ = __str__
cls.__str__ = lambda self: __str__(self).encode('utf-8')
if __repr__ is not None:
cls.__repr__ = lambda self: __repr__(self).encode('utf-8')
return cls
def ensure_text(value, encoding):
if isinstance(value, text_type):
return value
return value.decode(encoding)


if PY2: # pragma: no cover
unicode_type = unicode
else: # pragma: no cover
unicode_type = str
def ensure_str(value, encoding):
if isinstance(value, str):
return value
if PY2:
return value.encode(encoding)
else:
return value.decode(encoding)
101 changes: 101 additions & 0 deletions gb2260/code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from __future__ import absolute_import
from __future__ import unicode_literals

import re

from gb2260.exceptions import InvalidCode


# GB/T 2260 conformant code pattern.
# Every two digits form a province / prefecture / county layer subcode.
# NOTE: Whether a code has a corresponding division has to be considered along
# with a specific revision.
CODE_PATTERN = re.compile(
r'^(?P<province>\d\d)(?P<prefecture>\d\d)(?P<county>\d\d)$')


# The following province / prefecture / county code patterns are from the Spec.
# Subcode 00 is considered special, denoting the upper level division.
# When used as an argument, trailing 00s can be ommited.

# Province code
# e.g. 320000 / 3200 / 32
# NOTE: Allowing 320000 is an extension to the Spec.
PROVINCE_CODE_PATTERN = re.compile(r'^(?P<code>(?!00)\d\d)(?:00){0,2}$')

# Prefecture code
# e.g. 320200 / 3202
PREFECTURE_CODE_PATTERN = re.compile(r'^(?P<code>(?:(?!00)\d\d){2})(?:00)?$')

# County code
# e.g. 320203
COUNTY_CODE_PATTERN = re.compile(r'^(?P<code>(?:(?!00)\d\d){3})$')


def to_province(code):
"""Returns the corresponding province level division code.
:raises InvalidCode: if the code is not a valid GB/T 2260 code
:raises ValueError: the province level subcode is 00
"""
match = CODE_PATTERN.match(code)
if not match:
raise InvalidCode(code)
province = match.group('province')
if province == '00':
raise ValueError(code)
return '{0}0000'.format(province)


def to_prefecture(code):
"""Returns the corresponding prefecture level division code.
:raises InvalidCode: if the code is not a valid GB/T 2260 code
:raises ValueError: the province or prefecture level subcode is 00
"""
match = CODE_PATTERN.match(code)
if not match:
raise InvalidCode(code)
province = match.group('province')
prefecture = match.group('prefecture')
if province == '00' or prefecture == '00':
raise ValueError(code)
return '{0}{1}00'.format(province, prefecture)


def make_prefecture_pattern(province_code):
"""Returns a pattern for matching prefectures in the province.
:raises InvalidCode: if the province_code is not a valid province code.
"""
match = PROVINCE_CODE_PATTERN.match(province_code)
if not match:
raise InvalidCode(province_code)
raw = r'{0}(?!00)\d\d00'.format(match.group('code'))
return re.compile(raw)


def make_county_pattern(prefecture_code):
"""Returns a pattern for matching counties in the prefecture.
:raises InvalidCode: if the prefecture_code is not a valid prefecture code.
"""
match = PREFECTURE_CODE_PATTERN.match(prefecture_code)
if not match:
raise InvalidCode(prefecture_code)
raw = r'{0}(?!00)\d\d'.format(match.group('code'))
return re.compile(raw)


def split(code):
"""Returns codes for all the three level divisions.
:raises InvalidCode: if the code is not a valid GB/T 2260 code
"""
match = CODE_PATTERN.match(code)
if not match:
raise InvalidCode(code)
subcodes = match.groups()
province, prefecture, county = subcodes

codes = [
None if province == '00' else '{0}0000'.format(*subcodes),
None if prefecture == '00' else '{0}{1}00'.format(*subcodes),
None if county == '00' else '{0}{1}{2}'.format(*subcodes),
]
return codes
Loading