| Total Complexity | 56 | 
| Total Lines | 413 | 
| Duplicated Lines | 10.65 % | 
| Changes | 3 | ||
| Bugs | 0 | Features | 1 | 
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like CapakeyRestGateway often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # -*- coding: utf-8 -*-  | 
            ||
| 456 | class CapakeyRestGateway(CapakeyGateway):  | 
            ||
| 457 | '''  | 
            ||
| 458 | A REST gateway to the capakey webservice.  | 
            ||
| 459 | '''  | 
            ||
| 460 | |||
| 461 |     caches = {} | 
            ||
| 462 | |||
| 463 | View Code Duplication | def __init__(self, **kwargs):  | 
            |
| 464 | self.base_url = kwargs.get(  | 
            ||
| 465 | 'base_url',  | 
            ||
| 466 | 'http://geoservices.beta.informatievlaanderen.be:80/capakey/api/v0.1'  | 
            ||
| 467 | )  | 
            ||
| 468 |         self.base_headers = { | 
            ||
| 469 | 'Accept': 'application/json'  | 
            ||
| 470 | }  | 
            ||
| 471 | cache_regions = ['permanent', 'long', 'short']  | 
            ||
| 472 | for cr in cache_regions:  | 
            ||
| 473 | self.caches[cr] = make_region(key_mangler=str)  | 
            ||
| 474 | if 'cache_config' in kwargs:  | 
            ||
| 475 | for cr in cache_regions:  | 
            ||
| 476 |                 if ('%s.backend' % cr) in kwargs['cache_config']: | 
            ||
| 477 |                     log.debug('Configuring %s region on CapakeyRestGateway', cr) | 
            ||
| 478 | self.caches[cr].configure_from_config(  | 
            ||
| 479 | kwargs['cache_config'],  | 
            ||
| 480 | '%s.' % cr  | 
            ||
| 481 | )  | 
            ||
| 482 | |||
| 483 | View Code Duplication | def list_gemeenten(self, sort=1):  | 
            |
| 484 | '''  | 
            ||
| 485 | List all `gemeenten` in Vlaanderen.  | 
            ||
| 486 | |||
| 487 | :param integer sort: What field to sort on.  | 
            ||
| 488 | :rtype: A :class:`list` of :class:`Gemeente`.  | 
            ||
| 489 | '''  | 
            ||
| 490 | def creator():  | 
            ||
| 491 | url = self.base_url + '/municipality'  | 
            ||
| 492 | h = self.base_headers  | 
            ||
| 493 |             p = { | 
            ||
| 494 | 'orderbyCode': sort == 1  | 
            ||
| 495 | }  | 
            ||
| 496 | res = capakey_rest_gateway_request(url, h, p).json()  | 
            ||
| 497 | return [  | 
            ||
| 498 | Gemeente(r['municipalityCode'], r['municipalityName'])  | 
            ||
| 499 | for r in res['municipalities']  | 
            ||
| 500 | ]  | 
            ||
| 501 | if self.caches['permanent'].is_configured:  | 
            ||
| 502 | key = 'list_gemeenten_rest#%s' % sort  | 
            ||
| 503 | gemeente = self.caches['permanent'].get_or_create(key, creator)  | 
            ||
| 504 | else:  | 
            ||
| 505 | gemeente = creator()  | 
            ||
| 506 | for g in gemeente:  | 
            ||
| 507 | g.set_gateway(self)  | 
            ||
| 508 | return gemeente  | 
            ||
| 509 | |||
| 510 | def get_gemeente_by_id(self, id):  | 
            ||
| 511 | '''  | 
            ||
| 512 | Retrieve a `gemeente` by id (the NIScode).  | 
            ||
| 513 | |||
| 514 | :rtype: :class:`Gemeente`  | 
            ||
| 515 | '''  | 
            ||
| 516 | def creator():  | 
            ||
| 517 | url = self.base_url + '/municipality/%s' % id  | 
            ||
| 518 | h = self.base_headers  | 
            ||
| 519 |             p = { | 
            ||
| 520 | 'geometry': 'bbox',  | 
            ||
| 521 | 'srs': 31370  | 
            ||
| 522 | }  | 
            ||
| 523 | res = capakey_rest_gateway_request(url, h, p).json()  | 
            ||
| 524 | return Gemeente(  | 
            ||
| 525 | res['municipalityCode'],  | 
            ||
| 526 | res['municipalityName'],  | 
            ||
| 527 | res['geometry']['center'],  | 
            ||
| 528 | res['geometry']['boundingBox']  | 
            ||
| 529 | )  | 
            ||
| 530 | if self.caches['long'].is_configured:  | 
            ||
| 531 | key = 'get_gemeente_by_id_rest#%s' % id  | 
            ||
| 532 | gemeente = self.caches['long'].get_or_create(key, creator)  | 
            ||
| 533 | else:  | 
            ||
| 534 | gemeente = creator()  | 
            ||
| 535 | gemeente.set_gateway(self)  | 
            ||
| 536 | return gemeente  | 
            ||
| 537 | |||
| 538 | def list_kadastrale_afdelingen(self):  | 
            ||
| 539 | '''  | 
            ||
| 540 | List all `kadastrale afdelingen` in Flanders.  | 
            ||
| 541 | |||
| 542 | :param integer sort: Field to sort on.  | 
            ||
| 543 | :rtype: A :class:`list` of :class:`Afdeling`.  | 
            ||
| 544 | '''  | 
            ||
| 545 | def creator():  | 
            ||
| 546 | gemeentes = self.list_gemeenten()  | 
            ||
| 547 | res = []  | 
            ||
| 548 | for g in gemeentes:  | 
            ||
| 549 | res += self.list_kadastrale_afdelingen_by_gemeente(g)  | 
            ||
| 550 | return res  | 
            ||
| 551 | if self.caches['permanent'].is_configured:  | 
            ||
| 552 | key = 'list_afdelingen_rest'  | 
            ||
| 553 | afdelingen = self.caches['permanent'].get_or_create(key, creator)  | 
            ||
| 554 | else:  | 
            ||
| 555 | afdelingen = creator()  | 
            ||
| 556 | return afdelingen  | 
            ||
| 557 | |||
| 558 | def list_kadastrale_afdelingen_by_gemeente(self, gemeente, sort=1):  | 
            ||
| 559 | '''  | 
            ||
| 560 | List all `kadastrale afdelingen` in a `gemeente`.  | 
            ||
| 561 | |||
| 562 | :param gemeente: The :class:`Gemeente` for which the \  | 
            ||
| 563 | `afdelingen` are wanted.  | 
            ||
| 564 | :param integer sort: Field to sort on.  | 
            ||
| 565 | :rtype: A :class:`list` of :class:`Afdeling`.  | 
            ||
| 566 | '''  | 
            ||
| 567 | try:  | 
            ||
| 568 | gid = gemeente.id  | 
            ||
| 569 | except AttributeError:  | 
            ||
| 570 | gid = gemeente  | 
            ||
| 571 | gemeente = self.get_gemeente_by_id(gid)  | 
            ||
| 572 | gemeente.clear_gateway()  | 
            ||
| 573 | |||
| 574 | def creator():  | 
            ||
| 575 | url = self.base_url + '/municipality/%s/department' % gid  | 
            ||
| 576 | h = self.base_headers  | 
            ||
| 577 |             p = { | 
            ||
| 578 | 'orderbyCode': sort == 1  | 
            ||
| 579 | }  | 
            ||
| 580 | res = capakey_rest_gateway_request(url, h, p).json()  | 
            ||
| 581 | return [  | 
            ||
| 582 | Afdeling(  | 
            ||
| 583 | id=r['departmentCode'],  | 
            ||
| 584 | naam=r['departmentName'],  | 
            ||
| 585 | gemeente=gemeente  | 
            ||
| 586 | ) for r in res['departments']]  | 
            ||
| 587 | if self.caches['permanent'].is_configured:  | 
            ||
| 588 | key = 'list_kadastrale_afdelingen_by_gemeente_rest#%s#%s' % (gid, sort)  | 
            ||
| 589 | afdelingen = self.caches['permanent'].get_or_create(key, creator)  | 
            ||
| 590 | else:  | 
            ||
| 591 | afdelingen = creator()  | 
            ||
| 592 | for a in afdelingen:  | 
            ||
| 593 | a.set_gateway(self)  | 
            ||
| 594 | return afdelingen  | 
            ||
| 595 | |||
| 596 | def get_gemeente_for_kadastrale_afdeling(self, afdeling):  | 
            ||
| 597 | try:  | 
            ||
| 598 | aid = afdeling.id  | 
            ||
| 599 | except AttributeError:  | 
            ||
| 600 | aid = afdeling  | 
            ||
| 601 | |||
| 602 | afdelingen = self.list_kadastrale_afdelingen()  | 
            ||
| 603 | |||
| 604 | for a in afdelingen:  | 
            ||
| 605 | if a.id == aid:  | 
            ||
| 606 | return a.gemeente  | 
            ||
| 607 | |||
| 608 | raise GatewayResourceNotFoundException()  | 
            ||
| 609 | |||
| 610 | def get_kadastrale_afdeling_by_id(self, aid):  | 
            ||
| 611 | '''  | 
            ||
| 612 | Retrieve a 'kadastrale afdeling' by id.  | 
            ||
| 613 | |||
| 614 | :param aid: An id of a `kadastrale afdeling`.  | 
            ||
| 615 | :rtype: A :class:`Afdeling`.  | 
            ||
| 616 | '''  | 
            ||
| 617 | def creator():  | 
            ||
| 618 | g = self.get_gemeente_for_kadastrale_afdeling(aid)  | 
            ||
| 619 | url = self.base_url + '/municipality/%s/department/%s' % (g.id, aid)  | 
            ||
| 620 | h = self.base_headers  | 
            ||
| 621 |             p = { | 
            ||
| 622 | 'geometry': 'bbox',  | 
            ||
| 623 | 'srs': 31370  | 
            ||
| 624 | }  | 
            ||
| 625 | res = capakey_rest_gateway_request(url, h, p).json()  | 
            ||
| 626 | return Afdeling(  | 
            ||
| 627 | id=res['departmentCode'],  | 
            ||
| 628 | naam=res['departmentName'],  | 
            ||
| 629 | gemeente=g,  | 
            ||
| 630 | centroid=res['geometry']['center'],  | 
            ||
| 631 | bounding_box=res['geometry']['boundingBox']  | 
            ||
| 632 | )  | 
            ||
| 633 | if self.caches['long'].is_configured:  | 
            ||
| 634 | key = 'get_kadastrale_afdeling_by_id_rest#%s' % id  | 
            ||
| 635 | afdeling = self.caches['long'].get_or_create(key, creator)  | 
            ||
| 636 | else:  | 
            ||
| 637 | afdeling = creator()  | 
            ||
| 638 | afdeling.set_gateway(self)  | 
            ||
| 639 | return afdeling  | 
            ||
| 640 | |||
| 641 | def list_secties_by_afdeling(self, afdeling):  | 
            ||
| 642 | '''  | 
            ||
| 643 | List all `secties` in a `kadastrale afdeling`.  | 
            ||
| 644 | |||
| 645 | :param afdeling: The :class:`Afdeling` for which the `secties` are \  | 
            ||
| 646 | wanted. Can also be the id of and `afdeling`.  | 
            ||
| 647 | :rtype: A :class:`list` of `Sectie`.  | 
            ||
| 648 | '''  | 
            ||
| 649 | try:  | 
            ||
| 650 | aid = afdeling.id  | 
            ||
| 651 | except AttributeError:  | 
            ||
| 652 | aid = afdeling  | 
            ||
| 653 | afdeling = self.get_kadastrale_afdeling_by_id(aid)  | 
            ||
| 654 | afdeling.clear_gateway()  | 
            ||
| 655 | |||
| 656 | def creator():  | 
            ||
| 657 | url = self.base_url + '/municipality/%s/department/%s/section' % (afdeling.gemeente.id, afdeling.id)  | 
            ||
| 658 | h = self.base_headers  | 
            ||
| 659 |             p = { | 
            ||
| 660 | 'geometry': 'bbox',  | 
            ||
| 661 | 'srs': 31370  | 
            ||
| 662 | }  | 
            ||
| 663 | res = capakey_rest_gateway_request(url, h, p).json()  | 
            ||
| 664 | return [  | 
            ||
| 665 | Sectie(  | 
            ||
| 666 | r['sectionCode'],  | 
            ||
| 667 | afdeling  | 
            ||
| 668 | ) for r in res['sections']  | 
            ||
| 669 | ]  | 
            ||
| 670 | if self.caches['long'].is_configured:  | 
            ||
| 671 | key = 'list_secties_by_afdeling_rest#%s' % aid  | 
            ||
| 672 | secties = self.caches['long'].get_or_create(key, creator)  | 
            ||
| 673 | else:  | 
            ||
| 674 | secties = creator()  | 
            ||
| 675 | for s in secties:  | 
            ||
| 676 | s.set_gateway(self)  | 
            ||
| 677 | return secties  | 
            ||
| 678 | |||
| 679 | def get_sectie_by_id_and_afdeling(self, id, afdeling):  | 
            ||
| 680 | '''  | 
            ||
| 681 | Get a `sectie`.  | 
            ||
| 682 | |||
| 683 | :param id: An id of a sectie. eg. "A"  | 
            ||
| 684 | :param afdeling: The :class:`Afdeling` for in which the `sectie` can \  | 
            ||
| 685 | be found. Can also be the id of and `afdeling`.  | 
            ||
| 686 | :rtype: A :class:`Sectie`.  | 
            ||
| 687 | '''  | 
            ||
| 688 | try:  | 
            ||
| 689 | aid = afdeling.id  | 
            ||
| 690 | except AttributeError:  | 
            ||
| 691 | aid = afdeling  | 
            ||
| 692 | afdeling = self.get_kadastrale_afdeling_by_id(aid)  | 
            ||
| 693 | afdeling.clear_gateway()  | 
            ||
| 694 | |||
| 695 | def creator():  | 
            ||
| 696 | url = self.base_url + '/municipality/%s/department/%s/section/%s' % (afdeling.gemeente.id, afdeling.id, id)  | 
            ||
| 697 | h = self.base_headers  | 
            ||
| 698 |             p = { | 
            ||
| 699 | 'geometry': 'bbox',  | 
            ||
| 700 | 'srs': 31370  | 
            ||
| 701 | }  | 
            ||
| 702 | res = capakey_rest_gateway_request(url, h, p).json()  | 
            ||
| 703 | return Sectie(  | 
            ||
| 704 | res['sectionCode'],  | 
            ||
| 705 | afdeling,  | 
            ||
| 706 | res['geometry']['center'],  | 
            ||
| 707 | res['geometry']['boundingBox'],  | 
            ||
| 708 | )  | 
            ||
| 709 | if self.caches['long'].is_configured:  | 
            ||
| 710 | key = 'get_sectie_by_id_and_afdeling_rest#%s#%s' % (id, aid)  | 
            ||
| 711 | sectie = self.caches['long'].get_or_create(key, creator)  | 
            ||
| 712 | else:  | 
            ||
| 713 | sectie = creator()  | 
            ||
| 714 | sectie.set_gateway(self)  | 
            ||
| 715 | return sectie  | 
            ||
| 716 | |||
| 717 | def parse_percid(self, capakey):  | 
            ||
| 718 | import re  | 
            ||
| 719 | match = re.match(  | 
            ||
| 720 |             r"^([0-9]{5})([A-Z]{1})([0-9]{4})\/([0-9]{2})([A-Z\_]{1})([0-9]{3})$", | 
            ||
| 721 | capakey  | 
            ||
| 722 | )  | 
            ||
| 723 | if match:  | 
            ||
| 724 | percid = match.group(1) + '_' + match.group(2) +\  | 
            ||
| 725 | '_' + match.group(3) + '_' + match.group(5) + '_' +\  | 
            ||
| 726 | match.group(6) + '_' + match.group(4)  | 
            ||
| 727 | return percid  | 
            ||
| 728 | else:  | 
            ||
| 729 | raise ValueError(  | 
            ||
| 730 | "Invalid Capakey %s can't be parsed" % capakey  | 
            ||
| 731 | )  | 
            ||
| 732 | |||
| 733 | def parse_capakey(self, percid):  | 
            ||
| 734 | import re  | 
            ||
| 735 | match = re.match(  | 
            ||
| 736 |             r"^([0-9]{5})_([A-Z]{1})_([0-9]{4})_([A-Z\_]{1})_([0-9]{3})_([0-9]{2})$", | 
            ||
| 737 | percid  | 
            ||
| 738 | )  | 
            ||
| 739 | if match:  | 
            ||
| 740 | capakey = match.group(1) + match.group(2) +\  | 
            ||
| 741 | match.group(3) + '/' + match.group(5) + '_' +\  | 
            ||
| 742 | match.group(6) + '_' + match.group(4)  | 
            ||
| 743 | return capakey  | 
            ||
| 744 | else:  | 
            ||
| 745 | raise ValueError(  | 
            ||
| 746 | "Invalid percid %s can't be parsed" % percid  | 
            ||
| 747 | )  | 
            ||
| 748 | |||
| 749 | def list_percelen_by_sectie(self, sectie, sort=1):  | 
            ||
| 750 | '''  | 
            ||
| 751 | List all percelen in a `sectie`.  | 
            ||
| 752 | |||
| 753 | :param sectie: The :class:`Sectie` for which the percelen are wanted.  | 
            ||
| 754 | :param integer sort: Field to sort on.  | 
            ||
| 755 | :rtype: A :class:`list` of :class:`Perceel`.  | 
            ||
| 756 | '''  | 
            ||
| 757 | sid = sectie.id  | 
            ||
| 758 | aid = sectie.afdeling.id  | 
            ||
| 759 | gid = sectie.afdeling.gemeente.id  | 
            ||
| 760 | sectie.clear_gateway()  | 
            ||
| 761 | def creator():  | 
            ||
| 762 | url = self.base_url + '/municipality/%s/department/%s/section/%s/parcel' % (gid, aid, sid)  | 
            ||
| 763 | h = self.base_headers  | 
            ||
| 764 | res = capakey_rest_gateway_request(url, h).json()  | 
            ||
| 765 | return [  | 
            ||
| 766 | Perceel(  | 
            ||
| 767 | r['perceelnummer'],  | 
            ||
| 768 | sectie,  | 
            ||
| 769 | r['capakey'],  | 
            ||
| 770 | self.parse_percid(r['capakey']),  | 
            ||
| 771 | ) for r in res['parcels']  | 
            ||
| 772 | ]  | 
            ||
| 773 | if self.caches['short'].is_configured:  | 
            ||
| 774 | key = 'list_percelen_by_sectie_rest#%s#%s#%s' % (gid, aid, sid)  | 
            ||
| 775 | percelen = self.caches['short'].get_or_create(key, creator)  | 
            ||
| 776 | else:  | 
            ||
| 777 | percelen = creator()  | 
            ||
| 778 | for p in percelen:  | 
            ||
| 779 | p.set_gateway(self)  | 
            ||
| 780 | return percelen  | 
            ||
| 781 | |||
| 782 | def get_perceel_by_id_and_sectie(self, id, sectie):  | 
            ||
| 783 | '''  | 
            ||
| 784 | Get a `perceel`.  | 
            ||
| 785 | |||
| 786 | :param id: An id for a `perceel`.  | 
            ||
| 787 | :param sectie: The :class:`Sectie` that contains the perceel.  | 
            ||
| 788 | :rtype: :class:`Perceel`  | 
            ||
| 789 | '''  | 
            ||
| 790 | sid = sectie.id  | 
            ||
| 791 | aid = sectie.afdeling.id  | 
            ||
| 792 | gid = sectie.afdeling.gemeente.id  | 
            ||
| 793 | sectie.clear_gateway()  | 
            ||
| 794 | def creator():  | 
            ||
| 795 | url = self.base_url + '/municipality/%s/department/%s/section/%s/parcel/%s' % (gid, aid, sid, id)  | 
            ||
| 796 | h = self.base_headers  | 
            ||
| 797 |             p = { | 
            ||
| 798 | 'geometry': 'bbox',  | 
            ||
| 799 | 'srs': 31370  | 
            ||
| 800 | }  | 
            ||
| 801 | res = capakey_rest_gateway_request(url, p, h).json()  | 
            ||
| 802 | return Perceel(  | 
            ||
| 803 | res['perceelnummer'],  | 
            ||
| 804 | sectie,  | 
            ||
| 805 | res['capakey'],  | 
            ||
| 806 | Perceel.get_percid_from_capakey(res['capakey']),  | 
            ||
| 807 | None,  | 
            ||
| 808 | None,  | 
            ||
| 809 | res['geometry']['center'],  | 
            ||
| 810 | res['geometry']['boundingBox']  | 
            ||
| 811 | )  | 
            ||
| 812 | if self.caches['short'].is_configured:  | 
            ||
| 813 | key = 'get_perceel_by_id_and_sectie_rest#%s#%s#%s' % (id, sectie.id, sectie.afdeling.id)  | 
            ||
| 814 | perceel = self.caches['short'].get_or_create(key, creator)  | 
            ||
| 815 | else:  | 
            ||
| 816 | perceel = creator()  | 
            ||
| 817 | perceel.set_gateway(self)  | 
            ||
| 818 | return perceel  | 
            ||
| 819 | |||
| 820 | def get_perceel_by_capakey(self, capakey):  | 
            ||
| 821 | '''  | 
            ||
| 822 | Get a `perceel`.  | 
            ||
| 823 | |||
| 824 | :param capakey: An capakey for a `perceel`.  | 
            ||
| 825 | :rtype: :class:`Perceel`  | 
            ||
| 826 | '''  | 
            ||
| 827 | def creator():  | 
            ||
| 828 | url = self.base_url + '/parcel/%s' % capakey  | 
            ||
| 829 | h = self.base_headers  | 
            ||
| 830 |             p = { | 
            ||
| 831 | 'geometry': 'bbox',  | 
            ||
| 832 | 'srs': 31370  | 
            ||
| 833 | }  | 
            ||
| 834 | res = capakey_rest_gateway_request(url, p, h).json()  | 
            ||
| 835 | return Perceel(  | 
            ||
| 836 | res['perceelnummer'],  | 
            ||
| 837 | Sectie(  | 
            ||
| 838 | res['sectionCode'],  | 
            ||
| 839 | Afdeling(  | 
            ||
| 840 | res['departmentCode'],  | 
            ||
| 841 | res['departmentName'],  | 
            ||
| 842 | Gemeente(res['municipalityCode'], res['municipalityName'])  | 
            ||
| 843 | )  | 
            ||
| 844 | ),  | 
            ||
| 845 | res['capakey'],  | 
            ||
| 846 | Perceel.get_percid_from_capakey(res['capakey']),  | 
            ||
| 847 | None,  | 
            ||
| 848 | None,  | 
            ||
| 849 | res['geometry']['center'],  | 
            ||
| 850 | res['geometry']['boundingBox']  | 
            ||
| 851 | )  | 
            ||
| 852 | if self.caches['short'].is_configured:  | 
            ||
| 853 | key = 'get_perceel_by_capakey_rest#%s' % capakey  | 
            ||
| 854 | perceel = self.caches['short'].get_or_create(key, creator)  | 
            ||
| 855 | else:  | 
            ||
| 856 | perceel = creator()  | 
            ||
| 857 | perceel.set_gateway(self)  | 
            ||
| 858 | return perceel  | 
            ||
| 859 | |||
| 860 | def get_perceel_by_percid(self, percid):  | 
            ||
| 861 | '''  | 
            ||
| 862 | Get a `perceel`.  | 
            ||
| 863 | |||
| 864 | :param percid: A percid for a `perceel`.  | 
            ||
| 865 | :rtype: :class:`Perceel`  | 
            ||
| 866 | '''  | 
            ||
| 867 | return self.get_perceel_by_capakey(  | 
            ||
| 868 | Perceel.get_capakey_from_percid(percid)  | 
            ||
| 869 | )  | 
            ||
| 1277 |